[SwiftUI] @State @Binding を理解する

Property wrapper を理解した後は、SwiftUI のキモとなっている @State, @Binding を説明します。
Swift[Swift] PropertyWrapper 手を動かして理解する(その1 wrappedValue) [Swift] PropertyWrapper 手を動かして理解する(その2 wrappedValue の初期化)[Swift] PropertyWrapper 手を動かして理解する(その2 wrappedValue の初期化) [Swift] PropertyWrapper 手を動かして理解する(その3 $ もしくは projectedValue の理解)

@State, @Binding の定義

property wrapper としての定義を見てみます。

以下では、

@State の定義

@State var value:Int とすると

wrappedValue : value
projectedValue: Binding<value>

@Binding の定義

@Binding var value:Int とすると

wrappedValue : value
projectedValue: Binding<value>

プチまとめ

@State と @Binding の違い

property wrapper 視点での interface 的には、違いはありません。

ですが、Binding では、transaction という情報を持つことで、変化についての情報を保持することができるようになっています。

Transaction についての Apple のドキュメントは、こちら

本題ではないので、説明は省きます。

MyState, MyBinding を作って使ってみる

MyState, MyBinding を作ってみる

Property wrapper の仕組み自体は、Swift 言語の仕様の一部ですので詳細が開示されています。

ですが、@State や @Binding は、SwiftUI の一部であり、使うことはできますが、実装の詳細は開示されていません。

Apple の説明で、@State は、source of truth であり、@Binding はあくまで、@State への reference であるというような説明がされているかと思います。

そこで、@MyState と @MyBinding を以下のように定義しました。

MyState

コード上にコメントを入れていますが、データの保存場所は、MyState の外部にあり、そこへの参照を保持します。
値をセットされるときには、データの保存場所にあるデータを書き換えるため、MyState という struct 自身の変更は発生しません。

projectValue としては、データ保存場所へのリファレンス MyBinding を返すようにしています。

MyBinding

MyState, MyBinding を使ってみる

以下のようなアプリを作って動作を見てみます。

MyStateMyBinding を使ったアプリ

MyStateMyBinding を使ったアプリ
以下が、ソースコード です。

MyState, MyBinding を使う SwiftUI コード

MyState, MyBinding には、画面のリフレッシュを行う仕組みを入れていないために、ダミーの ObservableObject を使ってリフレッシュするようにしています。

main

@State, @Binding を使っていませんが、Stepper の + ボタン、- ボタンを押下して、”refresh label” ボタンを押下すると、値が変更されていることがわかります。

# あくまで、機能性として近いものを実装したということで、Apple の実装とどれくらい近いかは不明です。例えば、値の更新について伝播させる仕組み等が入っていません。

@State という property wrapper では、 source of truth の場所を確保しデータを保存するようにしています。その上で projectValue として、その場所へのリファレンスを渡します。@Binding は、その保存場所へのリファレンスを保持する property wrapper で、保存場所へアクセスすることで、直接保存場所の値を変更することができます。

まとめ

イメージとしては、以下のようなイメージです。

Image: State, Binding

Image: @State, @Binding
@State, @Binding
  • @State は、source of truth を作り出す
  • @Binding は、source of truth へのリファレンスを保持する
  • @Binding 経由で source of truth を直接変更することができる
  • (補足) @State, @Binding で行っている、変更の伝播を実装するのは大変そう。

説明は以上です。
不明な点やおかしな点ありましたら、ご連絡いただけるとありがたいです。

コメントを残す

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