ReactorKit에서 View에서 action을 전달하고,
action에 따른 처리를 mutate()를 통해 Mutation으로 방출하여
reduce()에서 State 값을 변경시켰었죠.
View에서는 state값을 바인딩하여 값 변경 시 UI를 업데이트 시켜줍니다.

그렇다면 . . transform은 언제 쓰는데 . .?
Github를 보면 transform은 각각의 stream을 transform()한다 . .라고 나와있는데요.
Global States에서 많이 사용된다고 합니다.
처음에 ReactorKit을 접하고 읽었을 때는 뭔소린가 싶었지만 실제로 사용하고 나니까 이해가 수월하더라고요 !
먼저 Global States란 ?
예를 들어, currentUser가 바뀔 때마다 다른 View의 화면 또한 바뀌어하는 상황이 있다고 해볼게요.
그럼 이 currentUser는 Global State로 해당 state가 변할 때마다 Observable<Mutation>이 방출되어야겠죠.
그렇다면 transform()의 역할은 ?
ReactorKit에서는 Action→ Mutation → State 의 흐름으로 Global State가 없는데요.
이 때, transform(mutation:)을 통해 Global State를 Mutation으로 방출할 수 있습니다.
실제로 구현해보자 !
제가 구현해야하는 상황에 대해 설명해볼게요.
정보입력 화면 -> 생년월일 화면 전환하여 생일을 선택한 후, 완료 버튼을 누르면 해당 생년월일 화면이 dismiss됩니다.
그러면 정보입력 화면의 생년월일에 해당 생일로 업데이트 되어야 합니다.



자 그렇다면, 여기서 Global State는 뭘까요 ?
생일입니다 ! (2022년 12월 6일)
생일의 변경 사항에 따라 정보 입력 화면의 UI가 업데이트 되어야 하기 때문입니다.
코드를 살펴볼게요 !
InfoService
import RxSwift
enum InfoType {
case birth
}
enum InfoEvent {
case updateInfo(type: InfoType, content: String)
}
protocol InfoServiceProtocol {
var event: PublishSubject<InfoEvent> { get }
func updateBirth(to birth: String) -> Observable<String>
}
class InfoService: InfoServiceProtocol {
let event = PublishSubject<InfoEvent>()
func updateBirth(to birth: String) -> Observable<String> {
event.onNext(.updateInfo(type: .birth, content: birth))
return .just(birth)
}
}
Global State가 여러 개여서 InfoService를 생성해서 구현했습니다 !
updateBirth()를 통해 Observable을 방출하고 있습니다.
BirthReactor
var initialState: State
var service: InfoServiceProtocol
init(service: InfoServiceProtocol) {
self.initialState = State()
self.service = service
}
func mutate(action: Action) -> Observable<Mutation> {
switch action {
case .tapDoneButton(let birth):
return service.updateBirth(to: birth).map { _ in .dismiss }
}
}
birth를 넘겨줘야하는 BirthReactor 먼저 볼게요.
여기서 완료 버튼과 함께 아까 생성한 InfoService에서 updateBirth()를 호출하여 Observable을 방출하고 있습니다.
InfoReactor
var service: InfoServiceProtocol
init(service: InfoServiceProtocol) {
self.initialState = State()
self.service = service
}
func transform(mutation: Observable<Mutation>) -> Observable<Mutation> {
let event = service.event.flatMap { event -> Observable<Mutation> in
switch event {
case .updateInfo(type: let type, content: let birth):
if type == .birth {
return .just(.updateBirth(birth))
} else {
return .never()
}
}
}
return Observable.merge(mutation, event)
}
그렇다면 InfoReactor에서는 transform()을 통해 해당 Global State를 Mutation으로 변형하여 UI를 업데이트 해줘야겠죠 !
birth 변경사항을 받아 .updateBirth()를 방출하여 UI 업데이트를 할 수 있습니다.
가장 효율적인 방법인지는 모르겠지만 . . 이렇게 transform()을 사용해서 화면 간의 데이터 전달을 구현했습니다.
추후에 더 나은 방법이나 오류를 찾게 된다면 바로 업데이트하도록 하겠습니다 !
'iOS > ReactorKit' 카테고리의 다른 글
[ReactorKit] RxDataSources로 CollectionView 구현하기 (0) | 2022.11.17 |
---|---|
[ReactorKit] ReatorKit 살펴보기 (0) | 2022.11.10 |