まえがき
The Composable Architecture(以下からTCA)で、
親子や孫..のStateの共有をノード間で自動的に同期するためには
どうすればよいか備忘録として書き留めます。
おおまかに何がやりたいか
孫で更新された情報と、
親で更新された共有データ親に即座に更新される状態を作りたい。
TCAでSingletonを使うようなイメージ。
手順
共通に持ちたいSharedDataを定義
struct SharedData: Equatable {
var isFirstUser: Bool = false
}
共有の情報をSharedDataとして定義し、
struct AppState: Equatable {
var sharedData: SharedData
var _homeState: HomeState
}
extension AppState {
var homeState: HomeState {
get {
return _homeState.with(sharedData: sharedData)
}
set {
_homeState = newValue
sharedData = newValue.sharedData
}
}
}
extension AppState {
static func initial(sharedData: SharedData) -> AppState {
AppState(
sharedData: sharedData,
_homeState: .initial(sharedData: sharedData)
)
}
}
他の画面に遷移するときに、
Stateを初期化時にsharedStateを渡し、
更新があるたびにsetterを通じてsharedDataを更新します。
Rootに共通のStateを定義し、それを共有したいStateを初期化する時に注入し、
そのStateが更新されると共通のStateも更新させるようにすることで実現します。
struct HomeState: Equatable {
var sharedData: SharedData
}
extension HomeState {
static func initial(sharedData: SharedData) -> HomeState {
HomeState(sharedData: sharedData)
}
}
extension HomeState {
func with(sharedData: SharedData) -> Self {
var result = self
result.sharedData = sharedData
return result
}
}
上記コードをPlaygroundで試すと
var appState = AppState.initial()
appState.sharedData.isFirstUser // print true
// homeStateのsharedData経由でisFirstUserを更新させる。
appState.homeState.sharedData.isFirstUser = false
appState.sharedData.isFirstUser // print false
あとがき
Stateのノードのどこから更新しても更新できるようにするやり方でした。
本来ならAction経由でStateを更新するのが筋かもしれませんが、
一例として参考にしていただけたら幸いです。
SwiftUI x The Composable Architecture(TCA) x Firestoreでのお仕事募集中です〜!