맛동산이

SwiftUI) TCA - ifLet, 옵셔널 State를 언래핑하는법 - 화면전환이 필요할때 본문

앱/SwiftUI

SwiftUI) TCA - ifLet, 옵셔널 State를 언래핑하는법 - 화면전환이 필요할때

진ddang 2024. 9. 17. 04:37

TCA에서는 State와 Reducer가 서로 얽히고 설켜있는 상태를 보기가 쉽다.

특히나 화면전환에서는 SwiftUI에서는 상태값에 따른 화면 변화가 많은데, 이러한 경우 초기 값을 nil로 설정해주기 때문에 이러한 화면에 대한 언래핑이 필요하다.

SwiftUI 에서의 기본적인 화면 전환은 다음과 같다.

struct  MainView {
	@State var isUserLogged: Bool = false

  var body: some View {
	  if isUserLogged {
		  MainTabView()
		}
		else {
			LoginView()
		}
	}
}

이러한 경우 TCA에서는 해당 값을 State로 받아야하고 해당 State는 옵셔널 값이 되는데

이러한 옵셔널 State를 안전하게 언래핑 하는 방법이 바로 ifLet 이다.

ifLet

ifLet을 통해서 optional State를 안전하게 언래핑 하며, 해당 값이 들어왔을때 Reducer에 추가를 해줄수 있다.

이러한 경우 아래와 같은 특성을 가진다.

  • 자식과 부모 기능에서 특정 작업 순서를 강제화 (자식 > 부모 실행 순)
  • 자식 State가 nil이 되면 모든 자식의 이펙트를 자동으로 취소
  • 얼럿이나 컨펌과 같은 창에서 액션이 전송되면 자동으로 자식 nil을 무효화 처리함

→ 결론적으로는 ifLet 을 통해서 리듀서를 추가하면, 해당 이벤트가 먼저 발생하고, 상태가 다시 nil이되면 스트림이 끊어지는것과 같다.

이를 통해서 다음과 같은 순서로 위의 코드를 다음과 같이 작성할수 있다.

1. State 가 우선적으로 옵셔널 상태를 가진다.

@Reducer
struct MainViewStore {
	@ObservableState
	struct State {
		var ChildState: ChildStore.State?
	}
}

2. Reducer에 해당 State의 리듀서를 추가해준다.

    var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .test:
                return .none
            }
        }
        .ifLet(\\.child, action: /Action.child) {
		      ChildStore()
		    }
    }

3. 화면 처리를 해준다.

if let childStore = store.scope(state: \\.child, action: \\.child) {
  ChildView(store: childStore)
} else {
  Text("Nothing to show")
}

이전 버전에서는 ifLetStore라는것을 사용하였지만, TCA 1.7이상 버전에서는 if let 과 scope만으로 언래핑이 가능하다.

반응형