この節では2-5で作成したリストのプログラムをベースに, Appのデータを後から変更できるようにします. まず2-5までのコード作成が完了した状態をつくります.
- SFSwiftUI03-1.swiftpm を開く
(サンプルコード)
- 2-5を完了させるとできあがるコードとほぼ同様のものとなる
- ContentView : リスト画面
- MyApp : 起動時の処理
- PhotoData : 写真データ構造体
- SceneryDetail : 写真データの詳細画面
- SceneryRow : 写真リストのビュー
- ただし簡単のため, FoodAndDrink関連のデータと画面は除いている
- 2-5を完了させるとできあがるコードとほぼ同様のものとなる
コードの詳細は2-5-1を参考にしてください. 実行すると次のような画面の動きになります.
起動したとき
リスト項目を押して画面遷移
今回は, このコードをスタートにまずデータを変更できるように変更します.
- ContentViewを開き, var photos を @State var photos に変更する
- ForEachに使うデータをphotosから$photosに変更する
- 繰り返しで得られるデータがBinding型になる. 変数名も bind_photo にしてわかりやすくする
- SceneryDetailにbind_photoを渡す
- SceneryRowにbind_photoを直接渡せないため, bind_photo.wrappedValue を指定する. Bindingで包んだ中身(PhotoData型)を取り出せる
コード1
|
|
@Stateをつけたことでphotosは値を変更できるようになりました. しかしphotosが [PhotoData]型からState<[PhotoData]>型に変わった ことで, ForEachで得られる値も Binding
遷移先のSceneryDetailにも変更できるこの値を渡したいので, SceneryDetailも@Bindingを追加して受け取れるようにします. またせっかくのBinding型で値を変更できるので, 編集できるような工夫もしてみます.
-
SceneryDetailを開き, var photoを @Binding var photo に変更する
- 値が変更できるようになり, かつBindingへの変更は大元のStateにも伝わるようになる
-
タイトルを編集できるようText( data.title )を TextField( “タイトル”, text:$data.title ) に変更する
- TextFieldには, Binding型を渡す必要があるため, $data.title を渡す
コード2
|
|
dataに@Bindingを追加することで, ContentViewの@Stateの値を受け取れるようになりました. またdataのタイトル表示をTextFieldに変更したため, 値が変更できるようになりました. SceneryDetailでタイトルを変更すると, 元のリストの値も変わっていることがわかります.
SceneryDetailでタイトルを変更
戻ったリストでタイトル変更が反映されている