15
15

【Swift】Observation基本の基。

Last updated at Posted at 2024-02-08

はじめに

WWDC23で発表された新たなフレームワークのObservationの使い方を少しばかり勉強したのでアウトプットです。
今までのCombineとどのようにコードが変わるかを紹介していきます。

この記事でわかること

  • Observationってどんなものか
  • Observationを使ってとりあえずプログラムを動かす方法
  • Combineと比較して何が変わったのか

想定読者

  • SwiftUI触ったことあるよーという人
  • ObservableObject使ったことあるよーという人

この記事で説明していないこと

  • UIKitとObservationを合わせてどう使うかについて
  • @Bindableなどのプロパティラッパーについて

Observationって?

  • WWDC23で発表された新たなフレームワークです
  • Combineの進化系。みたいなイメージでいいと思いいます
  • iOS17からのみ使用可能です

今回作るサンプル

  • とてもシンプルなサンプルです。「add peach」ボタンタップするとリストに「もも」が追加されていきます。このサンプルを使ってObservationの使い方をCombineと比較しながら紹介します。ぜんぜん関係ないですが、「シンプルなサンプル」って韻踏んでていいっすね。

Simulator Screen Recording - iPhone 15 - 2024-02-08 at 17.44.06.gif

Combineを使った書き方

まずはCombineフレームワークに含まれるObservableObjectを使った書き方です

ViewModelのコード

import Combine

final class ObservableObjectFruitViewModel: ObservableObject {

    @Published var fruits = ["りんご", "ばなな", "みかん", "ぶどう", "さくらんぼ"]

    func tappedAddPeachButton() {
        fruits.append("もも")
    }
}

特徴

  • クラスにObservableObjectプロトコルを準拠させます
  • 監視したいプロパティに@Publishedを付与します
  • 監視したいプロパティが複数あれば、全てに@Publishedを付与する必要があります

Viewのコード


import SwiftUI

struct ContentView: View {

    @StateObject private var viewModel = ObservableObjectFruitViewModel()

    ~~ 省略 ~~
}

特徴

  • viewModelのプロパティに@StateObjectを付与

上記のように書くことで、viewModelのfruitsが監視され、変更が加わるとViewに自動的に反映されます。
では次にObservationだとどのように書くことができるか紹介します。

Observationを使った書き方

ViewModelのコード

import Observation

@Observable
final class ObservationFruitViewModel {

    var fruits = ["りんご", "ばなな", "みかん", "ぶどう", "さくらんぼ"]

    func tappedAddPeachButton() {
        fruits.append("もも")
    }
}

特徴

  • クラスに@Observableマクロを付与します
  • @Observableマクロを付与したクラスのプロパティは全て監視対象になります

Viewのコード

struct ContentView: View {

    @State private var viewModel = ObservationFruitViewModel()

   ~~ 省略 ~~
}

特徴

  • viewModelプロパティに@Stateを付与します。

上記のようにViewModelクラスには@Observableマクロを付与し、View側のviewModelプロパティに@Stateを付与することで、値を監視し、fruitsプロパティが変更されるとViewに反映されます。

ViewModelのプロパティを監視から外したい場合

Combine

@Publishedを削除すれば監視対象から外れます。

final class ObservableObjectFruitViewModel: ObservableObject {

    /* @Published */var fruits = ["りんご", "ばなな", "みかん", "ぶどう", "さくらんぼ"]

    func tappedAddPeachButton() {
        fruits.append("もも")
    }
}

Observation

@ObservationIgnoredを付与すれば監視対象から外れます。

@Observable
final class ObservationFruitViewModel {

    @ObservationIgnored  これをつける
    var fruits = ["りんご", "ばなな", "みかん", "ぶどう", "さくらんぼ"]

    func tappedAddPeachButton() {
        fruits.append("もも")
    }
}

上記のように監視対象から外せば、ボタンをタップしてもリストは変化しません

Observationのうれしいところ

Observationを使用することで、ViewModelで監視対象にするプロパティ全てにいちいち@Publishedを付与していく必要がないというのは楽ですね。付与し忘れるということも無くなりそうです。

それに加えてこの記事では詳しく書きませんが、@Bindingを使用した子Viewの更新にも差があります。
Observationを使用することで、変更があった子Viewのみを再描画するようになりました。これに関してはまたどこかで。

サンプルのViewのコード全体

  • Observationを使った実装のViewのコードです。Combineを使っている場合はViewModelのクラスが変わります。
import SwiftUI

struct ContentView: View {

    @State private var viewModel = ObservationFruitViewModel()

    var body: some View {
        VStack {

            Button("add peach") {
                viewModel.tappedAddPeachButton()
            }
            .padding(.vertical, 24)

            List(viewModel.fruits, id: \.self) { item in
                Text(item)
            }
        }
    }
}

今回のサンプル

おわりに

WWDC23ではCombineについての発表もなかったみたいなので、今後はObservationの時代になっていきそうですね。
ではでは!!

参考

15
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
15