apple/UIKit & ReactiveX
[ReactorKit] ReactorKit 공부하기 #7 View (programming)
lgvv
2022. 10. 1. 11:42
ReactorKit 공부하기 #7 View (programming)
ReactorKit의 많은 예제들이 스토리보드 기반으로 작성되어 있기에 코드 기반의 예제를 작성해 봄.
요약
1. 자주하는 실수 - ReactorKit 사용할 때
: 리액터 reference를 아무데도 안잡아줘서 deinit 되어서 결국 작동하지 않는 실수
2. 자주하는 실수 - bind 내부적으로 호출되는데 명시적으로 또 호출하는거
: init으로 할 수 있음.
우선 ReactorKit에 선언된 프로토콜 View를 열어보자.
extension 부분을 보면 알겠지만, bind가 호출되고 있음.
bind를 ViewDidLoad()에서 명시적으로 호출하지 않아도 된다.
✅ ViewController ✅
import UIKit
import ReactorKit
import RxSwift
import RxCocoa
class MyMemoViewController: UIViewController, View {
var disposeBag = DisposeBag()
typealias Reactor = MyMemoReactor
override func viewDidLoad() {
super.viewDidLoad()
setUI()
}
func bind(reactor: Reactor) {
// MARK: - Action
cancelButton.rx.tap
.map { Reactor.Action.didTapDismiss }
.bind(to: reactor.action)
.disposed(by: disposeBag)
// MARK: - State
reactor.state.map { $0.isDismissed }
.filter { $0 }
.withUnretained(self)
.bind { owner, _ in
owner.dismiss(animated: true)
}
.disposed(by: disposeBag)
}
// MARK: - Initialize
init(reactor: MyMemoReactor = Reactor(initialState: .init())) {
super.init(nibName: nil, bundle: nil)
self.reactor = reactor
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - UIComponents
var memoTextField = UITextView()
var comfirmButton = UIBarButtonItem(title: "✅", style: .plain, target: nil, action: nil)
var cancelButton = UIBarButtonItem(image: UIImage(systemName: "xmark"), style: .plain, target: nil, action: nil)
}
extension MyMemoViewController {
private func setUI() {
self.navigationItem.leftBarButtonItem = cancelButton
self.navigationItem.rightBarButtonItem = comfirmButton
cancelButton.tintColor = .yellow
comfirmButton.tintColor = .yellow
self.navigationController?.navigationBar.backgroundColor = .systemBlue
view.backgroundColor = .systemBlue
view.addSubview(memoTextField)
memoTextField.font = UIFont.systemFont(ofSize: 22.0)
memoTextField.layer.cornerRadius = 12
memoTextField.snp.makeConstraints {
$0.edges.equalTo(view.safeAreaLayoutGuide).inset(10)
}
}
}
✅ Reactor ✅
import RxSwift
import RxCocoa
import ReactorKit
import UIKit
class MyMemoReactor: Reactor {
enum Action {
case didTapDismiss
}
enum Mutation {
case dismiss(Bool)
}
struct State {
var isDismissed: Bool = false
}
let initialState: State
init(initialState: State) {
self.initialState = initialState
}
func mutate(action: Action) -> Observable<Mutation> {
print("mutate")
switch action {
case .didTapDismiss:
return .just(.dismiss(true))
}
}
func reduce(state: State, mutation: Mutation) -> State {
var newState = state
print("reduce")
switch mutation {
case .dismiss(let value):
print("called dissmiss \(value)")
newState.isDismissed = value
}
return newState
}
}