一起养成写作习惯!这是我参与「日新方案 4 月更文应战」的第25天,点击检查活动概况。

  • 本文首要介绍下RxDataSources

关于RxSwift 也有很多拓宽,咱们比较常用的便是RxCocoa ,关于Tableview或者collectionView也有封装,里面还有其他的拓宽,感兴趣的能够看看 RxSwiftCommunity)

RxSwift学习-22-RxDataSources的使用

1. RxCocoa

咱们正常写的话便是初始化,签订署理,完成署理。

RxSwift学习-22-RxDataSources的使用

那么运用RxCocoa怎么完成呢?咱们展现的话

let items = Observable.just([
      "First Item",
      "Second Item",
      "Third Item"
    ])
    items
    .bind(to: tableView.rx.items) { (tableView, row, element) in
      let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell")!
      cell.textLabel?.text = "\(element) @ row \(row)"
      return cell
    }
    .disposed(by: disposeBag)

RxSwift学习-22-RxDataSources的使用

不需求签订协议,直接绑定到咱们的tableview上,这儿咱们也能够自己注册cell

  • tableView.rx.items
    items
      .bind(to: tableView.rx.items(cellIdentifier: "Cell", cellType: UITableViewCell.self)) { (row, element, cell) in
       cell.textLabel?.text = "\(element) @ row \(row)"
      }
      .disposed(by: disposeBag)

关于咱们tableView的一些署理事情也进行了封装

//点击事情
    tableView.rx.itemSelected
      .subscribe { indexPath in
       
        print("点击了\(indexPath.element!.row)")
      }.disposed(by: disposeBag)

RxSwift学习-22-RxDataSources的使用

但是咱们关于有的比如返回tableView的行高级,就没有封装,咱们这时候能够设置delegate来完成

tableView.rx.setDelegate(self)
      .disposed(by: disposeBag)

咱们完成详细署理

RxSwift学习-22-RxDataSources的使用

关于一些杂乱的分组等,咱们能够运用 RxDataSources

2. RxDataSources

咱们先看下简略的分组运用首要咱们看下sectionModel

RxSwift学习-22-RxDataSources的使用

当然咱们也能够自己自定义

struct MySection {
  var header: String
  var items: [Item]
}
extension MySection : AnimatableSectionModelType {
  typealias Item = Int
  var identity: String {
    return header
  }
  init(original: MySection, items: [Item]) {
    self = original
    self.items = items
  }
}

咱们创立datasource

tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
    let dataSource1 = RxTableViewSectionedAnimatedDataSource<MySection>(
      configureCell: { ds, tv, _, item in
        let cell = tv.dequeueReusableCell(withIdentifier: "Cell") ?? UITableViewCell(style: .default, reuseIdentifier: "Cell")
        cell.textLabel?.text = "Item \(item)"
        return cell
      },
      titleForHeaderInSection: { ds, index in
        return ds.sectionModels[index].header
      }
    )
    self.dataSource = dataSource1
    let sections = [
      MySection(header: "First section", items: [
        1,
        2
      ]),
      MySection(header: "Second section", items: [
        3,
        4
      ])
    ]
    Observable.just(sections)
      .bind(to: tableView.rx.items(dataSource: dataSource1))
      .disposed(by: disposeBag)

运转作用

RxSwift学习-22-RxDataSources的使用

  • 不同数据源的分组
enum MultipleSectionModel {
  case ImageProvidableSection(title: String, items: [SectionItem])
  case ToggleableSection(title: String, items: [SectionItem])
  case StepperableSection(title: String, items: [SectionItem])
}
enum SectionItem {
  case ImageSectionItem(image: UIImage, title: String)
  case ToggleableSectionItem(title: String, enabled: Bool)
  case StepperSectionItem(title: String)
}
extension MultipleSectionModel: SectionModelType {
  typealias Item = SectionItem
 
  var items: [SectionItem] {
    switch self {
    case .ImageProvidableSection(title: _, items: let items):
      return items.map { $0 }
    case .StepperableSection(title: _, items: let items):
      return items.map { $0 }
    case .ToggleableSection(title: _, items: let items):
      return items.map { $0 }
    }
  }
 
  init(original: MultipleSectionModel, items: [Item]) {
    switch original {
    case let .ImageProvidableSection(title: title, items: _):
      self = .ImageProvidableSection(title: title, items: items)
    case let .StepperableSection(title, _):
      self = .StepperableSection(title: title, items: items)
    case let .ToggleableSection(title, _):
      self = .ToggleableSection(title: title, items: items)
    }
  }
}

这儿运用枚举展现定义不同的cell款式,和Item。咱们处理数据dataSource

static func dataSource() -> RxTableViewSectionedReloadDataSource<MultipleSectionModel> {
    return RxTableViewSectionedReloadDataSource<MultipleSectionModel>(
      configureCell: { dataSource, table, idxPath, _ in
        switch dataSource[idxPath] {
        case let .ImageSectionItem(image, title):
          let cell: ImageTitleTableViewCell = table.dequeueReusableCell(forIndexPath: idxPath)
          cell.configure(image: image, title: title)
          return cell
        case let .StepperSectionItem(title):
          let cell: TitleSteperTableViewCell = table.dequeueReusableCell(forIndexPath: idxPath)
          cell.configure(title: title)
          return cell
        case let .ToggleableSectionItem(title, enabled):
          let cell: TitleSwitchTableViewCell = table.dequeueReusableCell(forIndexPath: idxPath)
          cell.configure(title: title, isEnabled: enabled)
          return cell
        }
      },
      titleForHeaderInSection: { dataSource, index in
        let section = dataSource[index]
        return section.title
      }
    )
  }
}

咱们tableView绑定咱们datasource

let sections: [MultipleSectionModel] = [
      .ImageProvidableSection(title: "Section 1",
        items: [.ImageSectionItem(image: UIImage(named: "settings")!, title: "General")]),
      .ToggleableSection(title: "Section 2",
        items: [.ToggleableSectionItem(title: "On", enabled: true),.ToggleableSectionItem(title: "Off", enabled: false)]),
      .StepperableSection(title: "Section 3",
        items: [.StepperSectionItem(title: "1"),.StepperSectionItem(title: "2"),.ToggleableSectionItem(title: "On", enabled: true)])
    ]
   
    let dataSource = ViewController.dataSource()
   
    Observable.just(sections)
      .bind(to: tableView.rx.items(dataSource: dataSource))
      .disposed(by: disposeBag)

运转作用

RxSwift学习-22-RxDataSources的使用

3. 对MJ封装

咱们通常也会对上拉改写和下拉加载更多进行分装,把咱们改写的事情转换为序列,并供给绑定。

extension Reactive where Base: UITableView {
  /// 改写
  var refresh: ControlEvent<RefreshType> {
    let source = Observable<RefreshType>.create { observer in
      if base.mj_header == nil {
        base.mj_header = MJRefreshNormalHeader(refreshingBlock: {
          observer.on(.next(.refresh))
        })
      }
     
      if base.mj_footer == nil {
        base.mj_footer = MJRefreshAutoNormalFooter(refreshingBlock: {
          observer.on(.next(.loadMore))
        })
      }
     
      return Disposables.create()
    }
   
    return ControlEvent(events: source)
  }
 
  /// 停止下拉改写
  var endRefresh: Binder<(RefreshType, Bool)> {
    Binder(base) { control, data in
      switch data.0 {
      case .refresh:
        control.mj_header?.endRefreshing()
        if data.1 {
          control.mj_footer?.endRefreshingWithNoMoreData()
        } else {
          control.mj_footer?.resetNoMoreData()
        }
      case .loadMore:
        control.mj_footer?.endRefreshing()
        if data.1 {
          control.mj_footer?.endRefreshingWithNoMoreData()
        }
      default:
        if data.1 {
          control.mj_footer?.endRefreshingWithNoMoreData()
        }
      }
     
    }
  }
}

其中RefreshType咱们定义为改写类型

enum RefreshType {
  case none
  case refresh
  case loadMore
}

4. 总结

关于一些简略的展现类的cell比较合适,但是关于一些负责的tableView,拓宽性不是很好,比如cell高度的设定,当然咱们自己也能够拓宽。看自己需求,灵活运用。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。