iOS/TCA
TCA Binding
dely
2024. 3. 5. 22:16
강의를 듣다가 새로운 것을 발견하여 기록한다.
기존에 TCA 아키텍처 기반으로 TextField의 text를 받아올 때 다음과 같이 사용했었다.
1)
import SwiftUI
import ComposableArchitecture
struct SomethingView: View {
let store: StoreOf<SomethingFeature>
@State var email: String = ""
var body: some View {
WithViewStore(self.store, observe: { $0 }) { viewStore in
VStack {
TextField("이메일을 입력하세요", text: $email)
.padding()
.onChange(of: email) {
viewStore.send(.textChanged($0))
}
Text(viewStore.email)
}
}
}
}
import ComposableArchitecture
struct SomethingFeature: Reducer {
struct State: Equatable {
var email: String = ""
}
enum Action: Equatable {
case textChanged(String)
}
var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .textChanged(let email):
state.email = email
return .none
}
}
}
}
email의 상태값을 onChange로 TCA Action에 viewStore.send 해서 사용을 했었다.
그런데 찾다보니 다음 방식으로도 쓸 수 있다는 것을 알았다.
viewStore.bindint(get: send:) 방식이다.
2)
struct SomethingView: View {
let store: StoreOf<SomethingFeature>
@State var email: String = ""
var body: some View {
WithViewStore(self.store, observe: { $0 }) { viewStore in
VStack {
TextField("이메일을 입력하세요", text: viewStore.binding(get: \\.email, send: { .textChanged($0) }))
.padding()
Text(viewStore.email)
}
}
}
}
그리고.. 강의를 듣다가 또 새로운 방법을 알게 되었다.
TCA 1.0에서 "BindingReducer"라는 것이 나왔고,
State 내 변수에 @BindingState 를 붙여주고,
Action에 BindableAction 프로토콜을 채택하여 binding(BindingAction<State>) case를 넣어주고,
Reducer에 BindingReducer() 를 넣어줌으로써
View 코드에서 viewStore.$email 로 접근하여 더 간편하게 쓸 수 있다.
3)
struct SomethingView: View {
let store: StoreOf<SomethingFeature>
@State var email: String = ""
var body: some View {
WithViewStore(self.store, observe: { $0 }) { viewStore in
VStack {
TextField("이메일을 입력하세요", text: viewStore.$email)
.padding()
Text(viewStore.email)
}
}
}
}
import ComposableArchitecture
struct SomethingFeature: Reducer {
struct State: Equatable {
@BindingState var email: String = ""
}
enum Action: Equatable, BindableAction {
case binding(BindingAction<State>)
}
var body: some ReducerOf<Self> {
BindingReducer()
Reduce { state, action in
switch action {
case .binding(_):
return .none
}
}
}
}
위의 1), 2), 3) 모두 동일하게 동작하는 것을 볼 수 있다.
반응형