Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- unowned
- weak
- regex
- 회고
- Async
- 광주소프트웨어마이스터고등학교
- UIImage
- MVVM
- Sync
- 회고록
- Clean Architecture
- GOMS
- ios
- xcode
- keychain
- DI
- breakpoint
- 정규식
- Swift
- RenderingMode
- 순환참조
- pop
- UIKit
- ReactorKit
- Protocol
- UISheetPresentationController
Archives
- Today
- Total
minaje
ReactorKit 본문
Reactor?

ReactorKit은 UI를 구성하는 View와 비지니스 로직은 담당하는 Reactor로 이루어져 있다.
View는 알겠는데 Reactor가 뭐지..!!
Reactor는 View에서 일어날 Action을 미리 정의해놓고! 그 Action이 일어나면 State를 View에게 보내는 형식으로 작동한다.
View는 Reactor에게 Action으로 보내고 State를 받아와서! UI를 변경하는 방식으로 작동한다.
자 이렇게 대충 개념은 알았으니 코드를 보며 사용하는 방법을 알아보자!
View!
ex) increaseButton 예시
- ReactorKit 내부적으로 호출되는 bind(reactor:) 메소드에서 바인딩 수행
- bindAction(_:): View에서 Reactor로 이벤트 방출
- bindState(_:): Reactor에서 바뀐 state들을 View에서 구독
- storyboard 이용 시 StoryboardView 구현
import UIKit
import RxSwift
import RxCocoa
import ReactorKit
class CounterViewController: UIViewController, StoryboardView {
var disposeBag = DisposeBag()
@IBOutlet weak var countLabel: UILabel!
@IBOutlet weak var increaseButton: UIButton!
func bind(reactor: CounterViewReactor) {
bindAction(reactor)
bindState(reactor)
}
private func bindAction(_ reactor: CounterViewReactor) {
increaseButton.rx.tap
.map { Reactor.Action.increase }
.bind(to: reactor.action)
.disposed(by: disposeBag)
}
private func bindState(_ reactor: CounterViewReactor) {
reactor.state
.map { String($0.value) }
.distinctUntilChanged()
.bind(to: countLabel.rx.text)
.disposed(by: disposeBag)
}
}
Reactor!
- Action
- View로부터 받을 Action을 enum으로 정의
- ex) increaseButtonDidTap
- Mutation
- View로부터 action을 받은 경우, 해야할 작업단위들을 enum으로 정의
- ex) increaseValue
- State
- 현재 상태를 기록하고 있으며, View에서 해당 정보를 사용하여 UI업데이트 및 Reactor에서 image를 얻어올때 page정보들을 저장
- mutate(action:) -> Observable<Mutation>
- Action이 들어온 경우, 어떤 처리를 할것인지 Mutation에서 정의한 작업 단위들을 사용하여 Observable로 방출
- 해당 부분에서, RxSwift의 concat 연산자를 이용하여 비동기 처리가 유용
- concat 연산자: 여러 Observable이 배열로 주어지면 순서대로 실행
- reduce(state:mutation:) -> State
- 현재 상태(state)와 작업 단위(mutation)을 받아서, 최종 상태를 반환
- mutate(action:) -> Observable<Mutation>이 실행된 후 바로 해당 메소드 실행
import Foundation
import RxSwift
import RxCocoa
import ReactorKit
class CounterViewReactor: Reactor {
let initialState = State()
enum Action {
case increase
case decrease
}
// 처리 단위
enum Mutation {
case increaseValue
case decreaseValue
case setLoading(Bool)
}
// 현재 상태를 기록
struct State {
var value = 0
var isLoading = false
}
// Action이 들어온 경우, 어떤 처리를 할건지 분기
func mutate(action: Action) -> Observable<Mutation> {
switch action {
case .increase:
return Observable.concat([
Observable.just(.setLoading(true)),
Observable.just(.increaseValue).delay(.seconds(1), scheduler: MainScheduler.instance),
Observable.just(.setLoading(false))
])
case .decrease:
return Observable.concat([
Observable.just(.setLoading(true)),
Observable.just(.decreaseValue).delay(.seconds(1), scheduler: MainScheduler.instance),
Observable.just(.setLoading(false))
])
}
}
// 이전 상태와 처리 단위를 받아서 다음 상태를 반환하는 함수
func reduce(state: State, mutation: Mutation) -> State {
var newState = state
switch mutation {
case .increaseValue:
newState.value += 1
case .decreaseValue:
newState.value -= 1
case .setLoading(let isLoading):
newState.isLoading = isLoading
}
return newState
}
}