🍄
マクロが実装されたTCAは導入しやすいかも?
TCAの導入で気になるところ
基本的に自分の勉強不足と、好みの部分があります。
-
WithViewStore
がよくわからない。 - しかも
body: some View
のTopにいる。 -
WithViewStore
がよくわからないので、Viewのライフサイクルが複雑そうに見える
マクロ導入後のTCA
@Reducer
, @ObservableState
というマクロが導入され、View部分をスッキリ宣言することができるようになります。
Swift 5.9以前のTCA
import SwiftUI
import ComposableArchitecture
struct CounterFeature: Reducer {
struct State: Equatable {
var count = 0
}
enum Action {
case decrementButtonTapped
case incrementButtonTapped
}
func reduce(into state: inout State, action: Action) -> Effect<Action> {
switch action {
case .decrementButtonTapped:
state.count -= 1
return .none
case .incrementButtonTapped:
state.count += 1
return .none
}
}
}
struct CounterView: View {
let store: StoreOf<CounterFeature>
var body: some View {
WithViewStore(self.store, observe: { $0 }) { viewStore in
VStack {
Text("\(viewStore.count)")
.padding()
.background(Color.yellow, in: .rect(cornerRadius: 10))
HStack {
Button("-") {
viewStore.send(.decrementButtonTapped)
}
.padding()
.background(Color.green, in: .rect(cornerRadius: 10))
Button("+") {
viewStore.send(.incrementButtonTapped)
}
.padding()
.background(Color.red, in: .rect(cornerRadius: 10))
}
}
.font(.largeTitle)
}
}
}
Swift 5.9からのTCA
import SwiftUI
import ComposableArchitecture
@Reducer
struct CounterFeature {
@ObservableState
struct State: Equatable {
var count = 0
}
enum Action {
case decrementButtonTapped
case incrementButtonTapped
}
var body: some Reducer<State, Action> {
Reduce { state, action in
switch action {
case .decrementButtonTapped:
state.count -= 1
return .none
case .incrementButtonTapped:
state.count += 1
return .none
}
}
}
}
struct CounterView: View {
let store: StoreOf<CounterFeature>
var body: some View {
VStack {
Text("\(store.count)")
.padding()
.background(Color.yellow, in: .rect(cornerRadius: 10))
HStack {
Button("-") {
store.send(.decrementButtonTapped)
}
.padding()
.background(Color.green, in: .rect(cornerRadius: 10))
Button("+") {
store.send(.incrementButtonTapped)
}
.padding()
.background(Color.red, in: .rect(cornerRadius: 10))
}
}
.font(.largeTitle)
}
}
変更点
Viewの本体(body)が標準の@Stateとほぼ同じフォーマットになりました。
これによりStateとActionを分離するだけの綺麗なアーキテクチャに見えるようになりました。
PointFree
PointFreeのライブラリはTCAが大きなライブラリですが、そもそもSwiftUIを使わない場面でも便利なライブラリが多いので、是非見てみてください。
Discussion