관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] RxSwift, dataSource 처리 방법 (단일 Section, tableView, collectionView) 본문

RxSwift/RxSwift 응용

[iOS - swift] RxSwift, dataSource 처리 방법 (단일 Section, tableView, collectionView)

jake-kim 2022. 1. 13. 22:04

* 주의: Section이 한개밖에 없는 경우 해당 방법 사용하고, 만약 Section이 여러개면 RxDataSource 사용 방법 포스팅 글 참고

Cell 준비

//  MyCell.swift

import UIKit

final class MyCell: UITableViewCell {
  private let label: UILabel = {
    let label = UILabel()
    label.font = .systemFont(ofSize: 24)
    label.textColor = .black
    return label
  }()
  
  override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    
    self.contentView.addSubview(self.label)
    self.label.translatesAutoresizingMaskIntoConstraints = false
    self.label.leftAnchor.constraint(equalTo: self.contentView.leftAnchor).isActive = true
    self.label.rightAnchor.constraint(equalTo: self.contentView.rightAnchor).isActive = true
    self.label.topAnchor.constraint(equalTo: self.contentView.topAnchor).isActive = true
    self.label.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor).isActive = true
  }
  
  override func prepareForReuse() {
    super.prepareForReuse()
    self.prepare(text: "")
  }
  
  func prepare(text: String) {
    self.label.text = text
  }
  
  @available(*, unavailable)
  required init?(coder: NSCoder) {
    fatalError()
  }
}

RxSwift의 dataSource 처리를 안하는 경우

(보통의 방법)

//  ViewController.swift

import UIKit
import RxSwift
import RxCocoa

final class ViewController: UIViewController {
  
  private let tableView: UITableView = {
    let view = UITableView()
    view.register(MyCell.self, forCellReuseIdentifier: "cell")
    return view
  }()
  
  private var dataSource = ["0"]
  
  override func viewDidLoad() {
    super.viewDidLoad()
    self.dataSource.append(contentsOf: (1...30).map(String.init))
    
    self.view.addSubview(self.tableView)
    self.tableView.translatesAutoresizingMaskIntoConstraints = false
    self.tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
    self.tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
    self.tableView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
    self.tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true

    self.tableView.dataSource = self
    self.tableView.reloadData()
  }
}

extension ViewController: UITableViewDataSource {
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    dataSource.count
  }
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyCell
    cell.prepare(text: self.dataSource[indexPath.row])
    return cell
  }
}

RxSwift 사용 방법

  • Section이 한개밖에 없는 경우 해당 방법 사용하고, 만약 Section이 여러개면 RxDataSource 사용 방법 포스팅 글 참고
  • 일반적인 방법보다 더욱 간편 (dataSource = self 델리게이트 소스 코드 불필요, 바인딩만 실시)
    • dataSource 준수 삭제
      // 삭제
      
      self.tableView.dataSource = self
      
      ...
      
      extension ViewController: UITableViewDataSource {
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
          dataSource.count
        }
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
          let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyCell
          cell.prepare(text: self.dataSource[indexPath.row])
          return cell
        }
      }​
  • DataSource를 Observable로 변경
    • tableView에 바인딩하기 위해 Observable 형태인 dataSource가 필요
      private var dataSource = Observable<[String]>.of((1...30).map(String.init))​
    • tableView에 바인딩
      self.dataSource
        .bind(to: self.tableView.rx.items) { tableView, row, item in
          let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: IndexPath(row: row, section: 0)) as! MyCell
          cell.prepare(text: item)
          return cell
        }
        .disposed(by: self.disposeBag)​

* 전체 소스 코드: https://github.com/JK0369/ExRxTableView

 

Comments