버그 잡이

ReactorKit - transform() 은 무엇일까? 본문

IOS

ReactorKit - transform() 은 무엇일까?

버그잡이 2022. 4. 6. 20:45

 

ReactorKit을 공부하면서 trasform()이라는 함수를 접하게 되었습니다.

 

"Action으로 Mutation(mutate() -> reduce()) 되어 State가 바뀐다."

 

이게 제가 이해한 ReactorKit의 기본 동작입니다.

transform() 낄 자리가 없어보이는데 도대체 어떤 역할을 하는 함수일까요?

 

 

Transform()

 

transform()을 이해하기에 없어서 ReactorKit의 전역 변수에 대해서 알아볼 필요가 있습니다.

공식 문서를 보면 ReactorKit은 전역 변수를 정의 하지 않는다고 합니다. 

Action -> Mutation -> State 플로우에서 전역변수가 낄 자리가 없는거죠.

 

그런데 Action이 아닌 전역변수의 변화로 인한 Mutation은 어떻게 처리해야할까요?

 

예를 들어, User 상태가 바뀌어서 화면을 변경해줘야 하는 경우가 있습니다.

이때는 특정 액션이 있는 것이 아니고 currentUser 라는 변수가 바뀜에 따라서 Mutation이 실행되어야 하는거죠.

var currentUser: BehaviorSubject<User> // global state

func transform(mutation: Observable<Mutation>) -> Observable<Mutation> {
  return Observable.merge(mutation, currentUser.map(Mutation.setUser))
}

 

이렇게 transform() 은 Action 없이도 Mutation이 가능하도록 도와주는 함수입니다.

 

 

 

Transform() 적용 예제 (5초 마다 시간 갱신)

 

 

연습용으로 만든 메모앱 입니다. 5초 마다 시간이 갱신되도록 만들었는데요.

 

class DateFactory {
    
    static let shared = DateFactory()
    
    private init() {}
    
    func getCurrentDate() -> String {
        let date = Date()
        let df = DateFormatter()
        df.dateFormat = "yyyy-MM-dd hh:mm:ss"
        let dateString = df.string(from: date)
        return dateString
    }
    
    func getDateEveryFiveSeconds() -> Observable<String> {
        Observable<Int>
          .timer(.seconds(1), period: .seconds(5), scheduler: MainScheduler.asyncInstance)
          .map { _ in self.getCurrentDate() }
          .distinctUntilChanged()
    }
}

 

class MainReactor: Reactor {
    var scheduler: Scheduler = SerialDispatchQueueScheduler(qos: .background)
    
    let dateMutation = DateFactory.shared.getDateEveryFiveSeconds()
        .flatMap { dateString -> Observable<Mutation> in
            return .just(.refreshDate(dateString))
        }
    
    enum Mutation {
        case refreshDate(String)
    }
    
    struct State {
        var date: String?
    }
    
    let initialState = State()
    
    func transform(mutation: Observable<Mutation>) -> Observable<Mutation> {
        return Observable.merge(mutation, dateMutation)
    }

    func reduce(state: State, mutation: Mutation) -> State {
        var newState = state
        
        switch mutation {
        case let .refreshDate(dateString):
            newState.date = dateString
        }
        
        return newState
    }
}

 
transform()을 활용하여 dateMutation 변수를 Mutation으로 발행하는 것을 볼 수 있습니다.

 

 

 

(제 개인 생각이 들어간 글로 잘못된 부분이 있을 수 있습니다. 잘못된 부분은 댓글로 지적부탁드립니다.)

 

 

*참조

https://github.com/ReactorKit/ReactorKit

 

 

 

반응형
Comments