apple/RxSwift, ReactorKit

[ReactorKit] ReactorKit 공부하기 #7 View (programming)

lgvv 2022. 10. 1. 11:42

ReactorKit 공부하기 #7 View (programming)

ReactorKit의 많은 예제들이 스토리보드 기반으로 작성되어 있기에 코드 기반의 예제를 작성해 봄.

 

들어가기 전에

리액터 킷을 사용할 때 내가 자주하는 실수 간단 정리

  • 리액터를 만들고 ViewContoller와 연결하지 않아서 이벤트가 발생하지 않는거
  • 내부적으로 bind를 호출하는데, 명시적으로 내가 작성해서 또 호출하는거

 

View 구현 코드 확인

내부적으로 bind 알아서 호출해주고 있음

ReactorKit 프로토콜 View

 

 

 

ViewController 코드 작성

리액터 킷 ViewContoller 작성

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