[SwiftUI][TCA] 基礎編
概要
この記事ではTCA初心者の筆者が理解を深めていくために、
pointfreeco公式のサンプルアプリを基に理解しやすく整理していきます。
今回からは1章として01GettingStartedの内容から整理していきます。
TCAとは
公式のソースとREADMEを見るのに加えて、
@yimajoさんが紹介している記事とiOSDCでの紹介動画を見ると、
概念としては大まかに理解出来ると思います。
またより詳細な情報は公式のGitHub Pagesで網羅されていますので、
このメソッドについて知りたいなどの場合は参考にしています。
今回扱うファイル
今回は公式サンプルのこちらのファイルです。
Counter
ここではTCAの基礎中の基礎を学びます。
+と-のボタンを押すと数字が変わるシンプルな実装です。

State,Action
他のアーキテクチャでも同様の概念があると思いますが、
StateとActionを以下のように定義します。
struct CounterState: Equatable {
var count = 0
}
enum CounterAction: Equatable {
case decrementButtonTapped
case incrementButtonTapped
}
Environment
このアプリでは使用していないので、何も処理がありません。
Environmentについては01-GettingStartedでは使用していませんので、
使用している02-Effectsでまた詳しく記載します。
struct CounterEnvironment {}
Reducer
ReducerではActionをSwitch文で分けStateに値を更新していきます。
それと同時にTCAの独特な概念として、
実行すべきEffectを各Actionでreturnします。
Effectについてはこのカウンターアプリでは.noneを返しており、
これはEmptyのEffectのことです。
後ほどEmptyではない返り値があるアプリ内で詳しく掘り下げます。
let counterReducer = Reducer<CounterState, CounterAction, CounterEnvironment> { state, action, _ in
switch action {
case .decrementButtonTapped:
state.count -= 1
return .none
case .incrementButtonTapped:
state.count += 1
return .none
}
}
View,Store
ここでSwiftUIのViewでStoreを参照できるよう、
WithViewStoreを使用します。
これ自体はSwiftUIのViewを返しているのでViewとなります。
WithViewStoreの引数にbodyの外で定義したStoreを渡すことで、
viewStore型でクロージャ内で使用することが出来ます。
このviewStoreに変換する意味合いとしては、
UIからのイベントをsendメソッドでActionとして送ることが出来ます。
struct CounterView: View {
let store: Store<CounterState, CounterAction>
var body: some View {
WithViewStore(self.store) { viewStore in
HStack {
Button("−") { viewStore.send(.decrementButtonTapped) }
Text("\(viewStore.count)")
.font(.body.monospacedDigit())
Button("+") { viewStore.send(.incrementButtonTapped) }
}
}
}
}
次回
次回はpullback・combine・scopeといったメソッドの使用を理解していきます。
記事はこちら
Discussion