teunteun2
[Swift] ReactorKit 본문
View <-> Reactor
그 사이에 Action stream 과 State stream 를 주고받는다
View -> (Action) -> Reactor
Reactor -> (State) -> View
디자인 의도
1. Testability -> View로부터 비즈니스 로직을 분리하기 위함
2. Small
3. Less Typing
-- View --
(아마 프로젝트에서는 ViewController & Cell 을 지칭할듯)
- 뷰는 그저 actionStream과 stateStream을 map 할지 를 정의하는 부분 (보내고 받기만 한다는 뜻인듯)
1 뷰를 정의할 땐, 리액트킷에 정의되어 있는 View 프로토콜을 채택하면 된다.
2 View 프로토콜을 채택하면 그 클래스는 자동으로 reactor라는 프로퍼티를 갖게됨.
3 이 프로퍼티에 나중에 생성하게 될 Reactor를 inject 해준다
class ProfileViewController: UIViewController, View {
var disposeBag = DisposeBag()
}
profileViewController.reactor = UserViewReactor() // inject reactor
4 할당해준 reactor 프로퍼티가 변경되었을 때 bind(reactor:) 이 호출된다. 이 메서드를 통해 action stream과 state stream의 bindings를 정의해주는 것임 !
-- Reactor --
- 리액터는 View의 state를 관리하는 UI-independent 계층이다
- 리액터의 가장 중요한 역할은 플로우를 뷰로부터 분리하는 것
- 모든 뷰는 응답하는 Reactor를 가지고 있고, 모든 로직을 Reactor에 위임한다.
- Reactor는 반대로 뷰에게 의존성이 전혀 없기 때문에, 쉽게 테스트 가능하다고 함
1 Reactor 프로토콜을 채택해서 생성한다. 이 프로토콜은 Action, Mutation, State 세 가지를 정의해주어야 함
2 ++ 추가로 initialState라는 프로퍼티도 필요함
class ProfileViewReactor: Reactor {
// represent user actions
enum Action {
case refreshFollowingStatus(Int)
case follow(Int)
}
// represent state changes
enum Mutation {
case setFollowing(Bool)
}
// represents the current view state
struct State {
var isFollowing: Bool = false
}
let initialState: State = State()
}
- Action : User interaction
- State : View state
- Mutation : Action & State 둘 간의 bridge
3 Reator은 Action stream을 State stream으로 mutate() , reduce() 두 단계를 거쳐 변환한다
-- mutate() --
- mutate()은 Action을 받아서 Observable<Mutation>을 return 하는 역할
- action을 정의할 때 enum으로 정의하기 때문에 mutate()에서 매개변수로 받아와 switch 문으로 각 action을 처리
func mutate(action: Action) -> Observable<Mutation> {
switch action {
case let .refreshFollowingStatus(userID): // receive an action
return UserAPI.isFollowing(userID) // create an API stream
.map { (isFollowing: Bool) -> Mutation in
return Mutation.setFollowing(isFollowing) // convert to Mutation stream
}
case let .follow(userID):
return UserAPI.follow()
.map { _ -> Mutation in
return Mutation.setFollowing(true)
}
}
}
-- reduce() --
- 이전 State & Mutation 을 바탕으로 새로운 State를 만드는 역할
func reduce(state: State, mutation: Mutation) -> State {
var state = state // create a copy of the old state
switch mutation {
case let .setFollowing(isFollowing):
state.isFollowing = isFollowing // manipulate the state, creating a new state
return state // return the new state
}
}
- 아하 그러니까 mutate() 메서드에서 action을 mutation으로 바꾼 것을 바탕으로 reduce() 메서드에서 새로운 state로 바꿔준다는 말인듯
'iOS' 카테고리의 다른 글
[Xcode] SwiftGen 적용하기 (0) | 2022.09.07 |
---|---|
[Swift] 키보드에 맞춰 ScrollView Content Inset 변경하기 (0) | 2022.05.21 |
[Swift] Collection View Cell 내부의 Button Action (tag & delegate & closure 차이점) 코드X (0) | 2022.05.10 |
[Swift] Extension NSMutableAttributedString (0) | 2022.05.08 |
[Swift] XIB를 이용한 커스텀 뷰 만들 때 - required init?(coder:NSCoder) & awakeFromNib() 의 호출 시점 (0) | 2022.05.07 |