티스토리 뷰

반응형

ReactorKit문서 를 보면 transform 함수에 대한 설명이 있습니다. 

transform은 mutate나 reduce 함수처럼 Reactor에 반드시 구현해야하는 함수가 아닙니다.

그래서 저는 최근에 알았는데, 까먹지 않게 정리해두려고 합니다.

 

 

Transform

 

transform 관련 함수는 이렇게 세개가 있습니다. 

 

이 함수들을 구현하여서 다른 observable stream들과 결합(combine) 할 수 있다고 합니다.

특히 transform(mutation:) 함수가 global event stream를 mutation stream과 결합하는 경우에 많이 쓰인다고 합니다.

 

잘 안와닿으니 더 구체적으로 살펴보겠습니다...!! 

그러기 위해서 우선 Global State에 대해서 알아야합니다.

 

Global State

 

우리가 일반적으로 Reactor를 쓸 때, Action → Mutation → State flow 로 쓰는데요,

이것은 Global State가 아닙니다. (no global state!!) 

 

사용자 정보를 담고 있는 global BehaviorSubject가 있다고 가정해볼게요.

하나 혹은 여러 Reactor에서 이 subject의 value가 변할때마다 알림을 받거나 사용자 정보에 접근하고 싶어한다고 해보겠습니다.

이것은 Global State 입니다. 

 

 

바로 이런 Global State에서 transform(mutation:)가 유용하게 쓰입니다. 

예를 들어 아래의 코드를 보겠습니다.

currentUser가 변할때마다 Reactor에서 Mutation.setUser(User?) 를 방출하고 싶어!!!! 할때 

transform(mutation:) 를 구현해주면 됩니다. 

 

보통 Action -> Mutation 플로우라서, Mutation을 방출하려면 reactor.action.onNext(.increase) 같은 코드를 실행시켜줘야하잖아요!!! 

근데 Action을 안거치고 바로 Mutation을 방출하겠다!!! 하는 것입니다. (신기☺️)

 

예제

저 함수를 쓰고 있는 RxTodo 프로젝트를 참고하여 완전 완전 간단한 예제를 작성해보겠습니다. 

 

https://github.com/devxoul/RxTodo

 

devxoul/RxTodo

iOS Todo Application using RxSwift and ReactorKit. Contribute to devxoul/RxTodo development by creating an account on GitHub.

github.com

 

예전에 작성한  ReactorKit 예제 따라하기  에서 사용한 예제 프로젝트를 이어서 진행해보겠습니다.

설정버튼을 하나 추가해줬고 사용자 이름을 저장 또는 취소 할 수 있는 기능을 추가했습니다. 

 

 

 

 

여기서 포인트는 " SettingViewReactor가 바꾼 global state에 대해 CounterViewReactor가 이벤트를 받고 Mutation을 방출한다. 왜냐하면 CounterViewReactor는 transform(mutation:) 함수를 구현했기 때문이다." 입니다. 

 

 

우선 UserService를 대충 하나 만들어줍니다. 

updateUserName함수가 불리면 event를 방출하는 부분이 포인트입니다.

 

 

 

 

그리고 CounterViewReactor가 service를 주입하도록 바꾸어줍니다, State에 UserName도 추가해주세요..! 

 

 

이 Reactor를 만들어주고있었던 ScenenDelegate에 가서 이니셜라이저 변경사항을 반영해주세요. 

 

 

그다음, SettingViewReactor를 만들어주세요 

service를 주입하도록 만들어주시고 service의 updateUserName함수를 사용하는 게 키포인트 입니다!

 

 

그리고 SettingViewController도 만들어주세요

 

 

 

CounterViewReactor에 아래 함수를 추가하고

 

 

CounterViewController의 설정 버튼에 액션을 추가해서 함수를 추가해서 저 버튼을 누르면 설정화면으로 갈 수있게 해주세요.

 

 

 

이제 드디어 CounterViewReactor에 transform 함수를 구현해보겠습니다!!+ 

그전에 Mutation에 updateUserName을 추가해주세요

 

 

 

 

service의 event가 방출되면 event 종류를 보고 원하는 Mutation 옵져버블을 만들어줍니다. (eventMutation이라고 부르겠습니다.)

eventMutation과 이 함수의 input으로 들어오는 mutation을 머지한 옵져버블을 리턴해줍니다. 

 

 

이 함수를 구현했으니까 이제 event가 방출될때마다 transform이 불려서 Mutataion을 방출해주고

Mutation 다음에 불리는 함수인 reduce가 불리게 됩니다. 

reduce에  .updateUserName 라는 케이스를 추가해주세요. 여기로 들어오게 됩니다. 

 

 

 

마지막으로 CounterViewController에 가서 userGreetingLabel을 만들어주고

state의 userName을 바인딩 해주면 끝-! 

 

 

transform(action:)과 transform(state:)

 

transform(mutation:) 외의 다른 transform 함수들도 동작원리가 비슷합니다.

말이 안되는 코드이지만 완전 대충 느낌만 내보자면 이런식으로 되겠습니다.

 

 

transform(action:) 은 Action을 방출하기 때문에 mutate(action:) 가 불립니다.

transform(state:) 은 State를 방출하기 때문에 reactor.state를 구독하고 있는 뷰 쪽 코드가 불립니다. 

 

 

 

소스코드

(위의 설명에 추가된 내용이 있는데, rxtodo 처럼 servcie-provider를 사용했습니다-!)

 

https://github.com/eunjin3786/ReactorKitPractice/tree/transfrom-functions

 

eunjin3786/ReactorKitPractice

ReactorKit 👍🍯👍. Contribute to eunjin3786/ReactorKitPractice development by creating an account on GitHub.

github.com

 

반응형
댓글