|
//
// UICollectionViewExt+rx.swift
// PaiAi
//
// Created by LISA on 2017/5/18.
// Copyright © 2017年 yb. All rights reserved.
//
import UIKit
import RxSwift
import RxCocoa
class FFCollectionViewReactiveArrayDataSourceSequenceWrapper<S: Sequence>
: FFCollectionViewReactiveArrayDataSource<S.Iterator.Element>
, RxCollectionViewDataSourceType {
typealias Element = S
init(cellFactory: @escaping CellFactory) {
super.init()
self.cellFactory = cellFactory
}
func collectionView(_ collectionView: UICollectionView, observedEvent: Event<S>) {
UIBindingObserver(UIElement: self) { collectionViewDataSource, sectionModels in
let sections = Array(sectionModels)
collectionViewDataSource.collectionView(collectionView, observedElements: sections)
}.on(observedEvent)
}
}
// Please take a look at `DelegateProxyType.swift`
class FFCollectionViewReactiveArrayDataSource<Element>
: NSObject, UICollectionViewDataSource
, SectionedViewDataSourceType {
var itemModels: [Element]? = nil
typealias CellFactory = (UICollectionView, Int, Element) -> UICollectionViewCell
typealias SupplementaryViewFactory = (UICollectionView, String, IndexPath) -> UICollectionReusableView
func modelAtIndex(_ index: Int) -> Element? {
return itemModels?[index]
}
func model(at indexPath: IndexPath) throws -> Any {
precondition(indexPath.section == 0)
guard let item = itemModels?[indexPath.item] else {
throw RxCocoaError.itemsNotYetBound(object: self)
}
return item
}
var cellFactory: CellFactory
var supplementaryViewFactory: SupplementaryViewFactory
override init() {
// super.init()
self.cellFactory = { _, _, _ in return (nil as UICollectionViewCell?)! }
self.supplementaryViewFactory = { _, _, _ in (nil as UICollectionReusableView?)! }
}
// data source
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return itemModels?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
return cellFactory(collectionView, indexPath.item, itemModels![indexPath.item])
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
return supplementaryViewFactory(collectionView, kind, indexPath)
}
func collectionView(_ collectionView: UICollectionView, observedElements: [Element]) {
self.itemModels = observedElements
collectionView.reloadData()
collectionView.collectionViewLayout.invalidateLayout()
}
}
extension Reactive where Base: UICollectionView {
public func items<S: Sequence, Cell: UICollectionViewCell, O: ObservableType>(cellIdentifier: String, supplementaryIdentifier: String, cellType: Cell.Type = Cell.self)
-> (_ source: O)
-> (_ configureCell: @escaping (Int, S.Iterator.Element, Cell) -> Void, @escaping (IndexPath, UICollectionReusableView, String) -> Void)
-> Disposable where O.E == S {
return { source in
return { (dataCell,supplement) in
let dataSource = FFCollectionViewReactiveArrayDataSourceSequenceWrapper<S>(cellFactory: {
(cv, i, item) in
let indexPath = IndexPath(item: i, section: 0)
let cell = cv.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! Cell
dataCell(i, item, cell)
return cell
})
dataSource.supplementaryViewFactory = {
(cv, kind, indexpath) in
let view = cv.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: supplementaryIdentifier, for: indexpath)
supplement(indexpath, view, kind)
return view
}
return self.items(dataSource: dataSource)(source)
}
}
}
}
|