RxSwift和UICollectionView标头

时间:2016-09-19 18:47:07

标签: ios swift uicollectionview rx-swift

我正在使用RxSwift我的UIViewController包含UICollectionView。我试图在我的集合视图中添加一个标题,但从未调用过:

func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath)

3 个答案:

答案 0 :(得分:4)

我有同样的问题。解决它转移到RxCollectionViewSectionedReloadDataSource

此类型的数据源具有页眉/页脚。标准版RxCollectionViewReactiveArrayDataSource没有页眉/页脚。

即使在RxCocoa UICollectionView+Rx扩展名中,也以RxCollectionViewSectionedReloadDataSource为例。

示例:

     let dataSource = RxCollectionViewSectionedReloadDataSource<SectionModel<String, Double>>()

     let items = Observable.just([
         SectionModel(model: "First section", items: [
             1.0,
             2.0,
             3.0
         ]),
         SectionModel(model: "Second section", items: [
             1.0,
             2.0,
             3.0
         ]),
         SectionModel(model: "Third section", items: [
             1.0,
             2.0,
             3.0
         ])
     ])

     dataSource.configureCell = { (dataSource, cv, indexPath, element) in
         let cell = cv.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! NumberCell
         cell.value?.text = "\(element) @ row \(indexPath.row)"
         return cell
     }

     items
        .bind(to: collectionView.rx.items(dataSource: dataSource))
        .disposed(by: disposeBag)

答案 1 :(得分:3)

经过很长一段时间搞清楚,我有一个完整的答案。关键部分取决于RxDataSources dataSource.configureCell dataSource.supplementaryViewFactory。

您需要通过正常注册笔尖进行设置。要使集合视图显示它的标题,您需要定义标题大小。使用集合流布局允许您保留单元格内部可能具有的任何绑定,而不是覆盖Rx委托代理RxCocoa在内部使用。

在这个例子中,我有一个viewModel用于整个屏幕,它包含一个RxVariable,其中包含一个itemViewModel数组,用于集合视图中的每个项目。

使用RxSwift,RxDataSources和RxCocoa的头文件的UICollectionView:

var disposeBag: DisposeBag? = DisposeBag()

@IBOutlet weak var collectionView: UICollectionView!

let dataSource = RxCollectionViewSectionedReloadDataSource<SectionModel<String, ItemViewModel>>()

override func viewDidLoad() {
    super.viewDidLoad()
    registerHeaderCell()
    registerCollectionViewCell()
    setupLayout()
    bindViewModelToCollectionView()
}

private func registerHeaderCell() {
    let nib = UINib(nibName: "HeaderCell", bundle: nil)
    collectionView.register(nib, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "HeaderReuseId")
}

private func registerCollectionViewCell() {
    let nib = UINib(nibName:"CollectionViewCell", bundle: nil)
    collectionView.register(nib, forCellWithReuseIdentifier: "CellReuseId")
}

private func setupLayout(){
    let layout = UICollectionViewFlowLayout()
    layout.headerReferenceSize = CGSize(width: UIScreen.main.bounds.width, height: 100)
    collectionView.setCollectionViewLayout(layout, animated: false)
}

private func bindViewModelToCollectionView(){
    dataSource.supplementaryViewFactory = {(dataSource, collectionView, kind, indexPath) -> UICollectionReusableView in
        let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "HeaderReuseId", for: indexPath) as! HeaderCell
        header.setup()
        return header
    }

    dataSource.configureCell = {(datasource, collectionView, indexPath, itemViewModel) -> UICollectionViewCell in
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CellReuseId", for: indexPath) as! CollectionViewCell
        cell.setup()
        return cell
    } 

    viewModel.itemViewModels.asObservable().map { 
        (itemViewModels) -> [SectionModel<String, ItemViewModel>] in
       //my particular app has one big section but you can use this for mutiple sections like Sergiy's answer   
         return [SectionModel(model: "", items: itemViewModels)]
    }.bind(to: collectionView.rx.items(dataSource: dataSource))
    .addDisposableTo(disposeBag!)
}

deinit {
    disposeBag = nil
}

答案 2 :(得分:-3)

除非您使用RxDataSources,否则与RxSwift无关。

您无法正确设置UICollectionView。除其他外:

  • 请务必定义func numberOfSections(in collectionView: UICollectionView) -> Int以返回大于0的内容。
  • 请务必定义func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize以返回大于CGSize(width: 0, height: 0)的尺寸。
  • 如果您使用的是nib,请将其注册为func register(_ nib: UINib?, forSupplementaryViewOfKind kind: String, withReuseIdentifier identifier: String)。或者,如果您以编程方式创建它,请将其注册到func register(_ viewClass: AnyClass?, forSupplementaryViewOfKind elementKind: String, withReuseIdentifier identifier: String)