[RxSwift] AirPortClone: UITableView & RxDataSources

Junyoung Park·2022년 12월 28일
0

RxSwift

목록 보기
20/25
post-thumbnail
post-custom-banner

#8 Airports UITableView Binding using RxDatasources - RxSwift MVVM Coordinator iOS App

AirPortClone: UITableView & RxDataSources

구현 목표

  • RxDataSources를 통한 테이블 뷰 구현

구현 태스크

  • 커스텀 테이블 뷰 구현

핵심 코드

typealias AirportItemsSection = SectionModel<Int, AirportViewPresentable>

protocol AirportsViewPresentable {
    typealias Input = (
    )
    typealias Output = (
        title: Driver<String>,
        airports: Driver<[AirportItemsSection]>
    )
    typealias Dependencies = (
        title: String,
        models: Set<AirportModel>
    )
    typealias ViewModelBuilder = (AirportsViewPresentable.Input) -> AirportsViewPresentable
    
    var input: AirportsViewPresentable.Input { get }
    var output: AirportsViewPresentable.Output { get }
}
  • 뷰 모델 빌더는 인풋을 받아 현재 프로토콜 자체를 리턴
  • 뷰 모델이 해당 AirportsViewPresentable을 따르기 때문에 사용 가능
override func start() {
        let vc = AirportsViewController()
        vc.viewModelBuilder = { [models] in
            let title = models.first?.city ?? ""
            return AirportsViewModel(input: $0, dependencies: (title: title, models: models))
        }
        self.navigationController.pushViewController(vc, animated: true)
    }
  • 뷰 모델 빌더의 클로저를 현재 AirportsCoordinator에서 넣어줌
  • 뷰 컨트롤러를 바인딩할 때 사용했던 데이터 모델 집합을 통해 뷰 모델을 구현
private func configureDataSource() {
        dataSource = .init(configureCell: { _, tableView, indexPath, item in
            guard let cell = tableView.dequeueReusableCell(withIdentifier: AirportTableViewCell.identifier, for: indexPath) as? AirportTableViewCell else { fatalError() }
            cell.configure(with: item)
            return cell
        })
    }
  • RxDataSources가 제공하는 섹션 모델을 커스텀, 해당 섹션 모델을 통해 데이터 소스를 구성
  • 데이터 소스를 표현하는 클로저 내부에서 실제 셀 UI 구성
private func bind() {
        guard let dataSource = dataSource else { return }
        viewModel?
            .output
            .airports
            .drive(tableView.rx.items(dataSource: dataSource))
            .disposed(by: disposeBag)
        viewModel?
            .output
            .title
            .drive(rx.title)
            .disposed(by: disposeBag)
    }
  • dataSource를 통해 테이블 뷰 UI 표현
  • rx.title은 뷰 컨트롤러 자체의 타이틀을 반응형으로 보여주는 듯

구현 화면

Coordinator 내에서 뷰 컨트롤러와 뷰 모델을 빌드, 연결하는 과정에 점점 더 익숙해지는 것 같긴 한데...

profile
JUST DO IT
post-custom-banner

0개의 댓글