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를 열어보자.

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
    }
}