SwiftUI 振る舞い基礎編(3) EnvironmentObjectとPublished

SwiftUI

     
⌛️ < 1 min.

前回で、Viewの階層に渡って、同じ変数を参照でき、更新が通知される@Bindingをチェックしました。
でも、@Bindingは、自分の子Viewにその度に渡さなければいけなくて、すこし面倒でした。

@EnvironmentObject

ビュー階層とは、別に存在して、参照することができるようにする仕組みです。
逆に、@Stateの変数は、SwiftUIがそのライフサイクルを管理してくれていましたが、@EnvironmentObjectは、自分で管理する必要があります。

@Published

@EnvironmentObjectで扱うクラスを自分で作る必要があるのですが、そのクラスの中で、監視対象となるべきプロパティには、”@Published”を属性として設定する必要があります。イメージとしては、@State属性をつける変数を自分で定義するクラスで保持するとすると、そのプロパティ(変数)に@Publishedとつける感じになります。

サンプル

自分で、ライフサイクルを管理する関係で、ContentViewを作成する段階で、自分でクラスをインスタンス化する必要があります。
コードを順番に載せますね

以下は、ViewModelです。このクラスが、それぞれのビューが表示したり入力したりするデータを保持するという想定です。

class MyViewModel:ObservableObject {
    @Published var count:Int = 0
}

ContentViewを作成する段階でMyViewModelをインスタンス化し、EnvironmentObjectとして登録します。
# SceneDelegate#Scene中で、インスタンス化して、登録する必要があります。
Let contentView = ContentView() の行を以下のように変更します。

let myViewModel = MyViewModel()
let contentView = ContentView().environmentObject(myViewModel)

これで、インスタンス化したMyViewModelが、EnvironmentObjectとして参照できるようになります。
参照の方法は、以下のコードです。

struct ContentView: View {
    @EnvironmentObject var myViewModel: MyViewModel
    var body: some View {
        HStack() {
            Button.init("-", action: {
                self.myViewModel.count = self.myViewModel.count - 1
            })
            SubView()
            Button.init("+", action: {
                self.myViewModel.count = self.myViewModel.count + 1
            })
        }
    }
}
struct SubView:View {
    @EnvironmentObject var myViewModel: MyViewModel
    var body: some View {
        VStack {
            Text("\(myViewModel.count)")
        }
    }
}

ポイントは、以下となります。

  • @EnvironmentObject属性をつけて変数を定義する。
  • どのビューからも参照できるので、ビュー間で受け渡ししなくて良い

まとめ

ここまでで、@State, @Binding, @EnvironmentObjectを見てきました。
複雑なアプリケーションを考え始めると、モデルを外部に持つことが多くなるでしょうから、@EnvironmentObjectを使うことが多くなるかと思います。
UIKitのときにも、AppDelegateに持たせて、受け取ったりしていたと思いますが、変数を属性をつけて宣言することで、受け取れてしまうのですから、すごいですよね。
アプリケーションのロジックや操作性に集中できる気がします。

本当に基本的な要素を説明したと思いますので、SwiftUI 振る舞い基礎編は、ここまでです。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です