我正在将RxSwift与包含UIViewControllerUICollectionView一起使用。我试图将 header 添加到我的收藏夹 View 中,但是从来没有这样称呼过:

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

最佳答案

经过长时间的研究,我得到了一个完整的答案。关键部分取决于RxDataSources dataSource.configureCell和dataSource.supplementaryViewFactory。
您将需要通过正常注册 Nib 进行设置。要使集合 View 显示其标题,您需要定义标题大小。使用收集流布局,可以保留Clickhandler单元内可能具有的所有绑定(bind),而不会覆盖RxCocoa在内部使用的rx委托(delegate)代理。
在此示例中,我为整个屏幕设置了一个viewModel,其中包含一个RxVariable以及用于集合 View 中每个项目的itemViewModels数组。
具有使用RxSwift,RxDataSources和RxCocoa的 header 的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: UICollectionView.elementKindSectionHeader, 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
}

关于ios - RxSwift和UICollectionView header ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39580085/

10-14 23:25