Created
June 29, 2018 06:46
-
-
Save yingmu52/b20f011c397912dc85d926353d716ba8 to your computer and use it in GitHub Desktop.
ksr datasource
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public protocol ValueCell: class { | |
associatedtype Value | |
static var defaultReusableId: String { get } | |
func configureWith(value: Value) | |
} | |
open class ValueCellDataSource: NSObject { | |
private var values: [[(value: Any, reusableId: String)]] = [] | |
open func configureCell(collectionCell cell: UICollectionViewCell, withValue value: Any) {} | |
open func configureCell(tableCell cell: UITableViewCell, withValue value: Any) {} | |
open func registerClasses(collectionView: UICollectionView?) {} | |
open func registerClasses(tableView: UITableView?) {} | |
public final func clearValues() { | |
self.values = [[]] | |
} | |
public final func clearValues(section: Int) { | |
self.padValuesForSection(section) | |
self.values[section] = [] | |
} | |
@discardableResult | |
public final func prependRow <Cell: ValueCell, Value: Any> | |
(value: Value, cellClass: Cell.Type, toSection section: Int) -> IndexPath | |
where Cell.Value == Value { | |
self.padValuesForSection(section) | |
self.values[section].insert((value, Cell.defaultReusableId), at: 0) | |
return IndexPath(row: 0, section: section) | |
} | |
@discardableResult | |
public final func appendRow <Cell: ValueCell, Value: Any> | |
(value: Value, cellClass: Cell.Type, toSection section: Int) -> IndexPath where Cell.Value == Value { | |
self.padValuesForSection(section) | |
self.values[section].append((value, Cell.defaultReusableId)) | |
return IndexPath(row: self.values[section].count - 1, section: section) | |
} | |
public final func appendStaticRow(cellIdentifier: String, toSection section: Int) { | |
self.padValuesForSection(section) | |
self.values[section].append(((), cellIdentifier)) | |
} | |
public final func set(cellIdentifiers: [String], inSection section: Int) { | |
self.padValuesForSection(section) | |
self.values[section] = cellIdentifiers.map { ((), $0) } | |
} | |
public final func appendSection <Cell: ValueCell, Value: Any> (values: [Value], cellClass: Cell.Type) | |
where Cell.Value == Value { | |
self.values.append(values.map { ($0, Cell.defaultReusableId) }) | |
} | |
public final func set <Cell: ValueCell, Value: Any> | |
(values: [Value], cellClass: Cell.Type, inSection section: Int) where Cell.Value == Value { | |
self.padValuesForSection(section) | |
self.values[section] = values.map { ($0, Cell.defaultReusableId) } | |
} | |
public final func set <Cell: ValueCell, Value: Any> | |
(value: Value, cellClass: Cell.Type, inSection section: Int, row: Int) | |
where Cell.Value == Value { | |
self.values[section][row] = (value, Cell.defaultReusableId) | |
} | |
public final subscript(indexPath: IndexPath) -> Any { | |
return self.values[indexPath.section][indexPath.item].value | |
} | |
public final subscript(itemSection itemSection: (item: Int, section: Int)) -> Any { | |
return self.values[itemSection.section][itemSection.item].value | |
} | |
public final subscript(section section: Int) -> [Any] { | |
return self.values[section].map { $0.value } | |
} | |
public final func numberOfItems() -> Int { | |
return self.values.reduce(0) { accum, section in accum + section.count } | |
} | |
public final func itemIndexAt(_ indexPath: IndexPath) -> Int { | |
return self.values[0..<indexPath.section] | |
.reduce(indexPath.item) { accum, section in accum + section.count } | |
} | |
} | |
// MARK: UITableViewDataSource methods | |
extension ValueCellDataSource: UITableViewDataSource { | |
public final func numberOfSections(in tableView: UITableView) -> Int { | |
return self.values.count | |
} | |
public final func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | |
return self.values[section].count | |
} | |
public final func tableView(_ tableView: UITableView, | |
cellForRowAt indexPath: IndexPath) -> UITableViewCell { | |
let (value, reusableId) = self.values[indexPath.section][indexPath.row] | |
let cell = tableView.dequeueReusableCell(withIdentifier: reusableId, for: indexPath) | |
self.configureCell(tableCell: cell, withValue: value) | |
return cell | |
} | |
final func reusableId(item: Int, section: Int) -> String? { | |
if !self.values.isEmpty && self.values.count >= section && | |
!self.values[section].isEmpty && self.values[section].count >= item { | |
return self.values[section][item].reusableId | |
} | |
return nil | |
} | |
final subscript(testItemSection itemSection: (item: Int, section: Int)) -> Any? { | |
let (item, section) = itemSection | |
if !self.values.isEmpty && self.values.count >= section && | |
!self.values[section].isEmpty && self.values[section].count >= item { | |
return self.values[itemSection.section][itemSection.item].value | |
} | |
return nil | |
} | |
private func padValuesForSection(_ section: Int) { | |
guard self.values.count <= section else { return } | |
(self.values.count...section).forEach { _ in | |
self.values.append([]) | |
} | |
} | |
} | |
// MARK: UICollectionViewDataSource methods | |
extension ValueCellDataSource: UICollectionViewDataSource { | |
public final func numberOfSections(in collectionView: UICollectionView) -> Int { | |
return self.values.count | |
} | |
public final | |
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { | |
return self.values[section].count | |
} | |
public final func collectionView(_ collectionView: UICollectionView, | |
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { | |
let (value, reusableId) = self.values[indexPath.section][indexPath.item] | |
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reusableId, for: indexPath) | |
self.configureCell(collectionCell: cell, withValue: value) | |
return cell | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment