ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TCA Binding
    iOS/TCA 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) 모두 동일하게 동작하는 것을 볼 수 있다.

     

    반응형

    'iOS > TCA' 카테고리의 다른 글

    TCA Toast  (0) 2024.03.04
    TCA 1.0 The Basic  (0) 2024.03.03

    댓글

Designed by Tistory.