swiftui

SwiftUIで用いるプロパティ3種について違いや使い所を解説

@State,@ObservedObject ,@EnvironmentObjectについてです。正式名称は「Property Wrappers」というらしいです。

三種類のプロパティタイプ

SwiftUIに持たせられるプロパティには次の3つがあります。

@State

値を再代入可能なプロパティです。

@ObservedObject

複数個のプロパティをまとめることができ、文字通りObjectとして扱うことができます。

@EnvironmentObject

アプリ全体から参照することができるObjectのプロパティです。

各プロパティについての解説

続いてこれらのプロパティがどのような振る舞いをするのかを詳しく解説します。説明のためにこのようなサンプルコードを利用します。定義したarticlesという変数のtitileをリスト状に表示するというものです。

sample
import SwiftUI

struct Next: View {
    
    private var articles: [Article]  = [
        Article(id: 0, title: "1番目"),
        Article(id: 1, title: "2番目"),
        Article(id: 2, title: "3番目")
    ]
    
    var body: some View {
        List(articles, id: \.id) { article in
            Row(article: article)
        }
    }   
}

struct Next_Previews: PreviewProvider {
    static var previews: some View {
        Next()
    }
}

デフォルトのプロパティの挙動

手始めにタップされるとタイトル情報の変更が行われるような挙動を実装してみます。SwiftUIではonTapGestureでタップイベントを取得できます。コードをこのように変更しましょう

var body: some View {
    List(articles, id: \.id) { article in
        Row(article: article)
    }	.onTapGesture {
          articles[0].title = "変更"
    }
}

するとエラーとなります。SwiftUIではViewがstruct(構造体)として定義されており、構造体が持つプロパティの値は再代入できません。

@State

ここで用いられるのが@Stateです。このようにprivate@Stateに書き換えます。

@State var articles: [Article]  = [
     Article(id: 0, title: "1番目"),
     Article(id: 1, title: "2番目"),
     Article(id: 3, title: "3番目")    
]

この状態で再度rowをタップしてみると今度は正常にtitleの値が変更された結果、表示されている文字列が変わるのが確認できます。このように定義された値を後ほど変更可能な@Stateプロパティですが、具体的な使い道としては例えばViewの状態管理に使うことができそうです。

補足: @Bindingを使った子Viewへの参照渡し

View間でデータを渡したい場合は@Bindingで定義することで、双方向データバインディングを行うことができます。詳しくは別記事で説明します。

@ObservedObject

クラスとして定義することが出来、Viewを生成するごとに使い回しが可能です。@Stateと違い多数のプロパティを管理することができます。

class uiPropertyObject: ObservableObject {
    @Published var isDark = false
    @Published var textColor = Color.red
}

各プロパティは@Publishedを付与して定義することで、変更のイベントを自動的に検知しViewに反映してくれるようになります。ですので基本的につけておく方が便利です。

struct Next: View {
    @ObservedObject var uiProperty: uiPropertyObject
}

具体的な使い道としてはUIKitを使ったかつての開発手法ではお馴染みのViewModelのように使うのが主流と思います。

@ObservedObject内の各プロパティの扱い方

@Publishedが付与されたプロパティはアプリ全体から参照可能になります。

@EnvironmentObject

アプリ全体を貫く共通のインスタンスを参照することができます。

参考記事

読んでいただきありがとうございます!!

記事として取り上げたトピックを体系化してまとめた内容を電子書籍として販売しています。購入していただくことで執筆の応援ができます。詳細はこちらから