Skip to content

Instantly share code, notes, and snippets.

@ka-interview
Created October 14, 2014 23:57
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ka-interview/a6478004c6cee552f225 to your computer and use it in GitHub Desktop.
Save ka-interview/a6478004c6cee552f225 to your computer and use it in GitHub Desktop.
Sketch of type safe, non-AnyObject-supporting data source
public protocol CountableCollectionType: CollectionType {
var count: Int { get }
}
extension Array: CountableCollectionType {}
public protocol CollectionViewCellFactoryType {
typealias Item
typealias Cell: UICollectionViewCell
func cellForItem(item: Item, inCollectionView collectionView: UICollectionView, atIndexPath indexPath: NSIndexPath) -> Cell
}
public struct RegisteredCollectionViewCellFactory<Cell: UICollectionViewCell, Item>: CollectionViewCellFactoryType {
private let reuseIdentifier: String
private let cellConfigurator: (Cell, Item) -> ()
public init(reuseIdentifier: String, cellConfigurator: (Cell, Item) -> ()) {
self.reuseIdentifier = reuseIdentifier
self.cellConfigurator = cellConfigurator
}
public func cellForItem(item: Item, inCollectionView collectionView: UICollectionView, atIndexPath indexPath: NSIndexPath) -> Cell {
// Will abort if you haven't already registered a cell of type Cell with the collection view under reuseIdentifier.
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as Cell
cellConfigurator(cell, item)
return cell
}
}
public class StaticCollectionViewDataSource<
SectionCollection: CountableCollectionType,
Factory: CollectionViewCellFactoryType,
ItemType
where
SectionCollection.Index == Int,
SectionCollection.Generator.Element: CountableCollectionType,
SectionCollection.Generator.Element.Generator.Element == ItemType,
SectionCollection.Generator.Element.Index == Int,
Factory.Item == ItemType> {
public var sections: SectionCollection
private let cellFactory: Factory
private let staticCollectionViewDataSourceBridge: StaticCollectionViewDataSourceBridge! // The bridge is initialized with a reference to self, so Swift thinks (correctly) that this could conceivably be used uninitialized.
public init(sections: SectionCollection, cellFactory: Factory) {
self.sections = sections
self.cellFactory = cellFactory
staticCollectionViewDataSourceBridge = StaticCollectionViewDataSourceBridge(
numberOfItemsInSectionHandler: { [weak self] in self?.numberOfItemsInSection($0) ?? 0 },
cellForItemAtIndexPathHandler: { [weak self] in self?.collectionView($0, cellForItemAtIndexPath: $1) },
numberOfSectionsHandler: { [weak self] in self?.numberOfSections() ?? 0 })
}
private func numberOfItemsInSection(section: Int) -> Int {
return sections[section].count
}
private func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let section = sections[indexPath.section]
let item: ItemType = section[indexPath.row]
return cellFactory.cellForItem(item, inCollectionView: collectionView, atIndexPath: indexPath)
}
private func numberOfSections() -> Int {
return sections.count
}
public var bridgedDataSource: UICollectionViewDataSource { return staticCollectionViewDataSourceBridge }
}
@objc private class StaticCollectionViewDataSourceBridge: NSObject, UICollectionViewDataSource {
private let numberOfItemsInSectionHandler: Int -> Int
private let cellForItemAtIndexPathHandler: (UICollectionView, NSIndexPath) -> UICollectionViewCell?
private let numberOfSectionsHandler: () -> Int
init(numberOfItemsInSectionHandler: Int -> Int, cellForItemAtIndexPathHandler: (UICollectionView, NSIndexPath) -> UICollectionViewCell?, numberOfSectionsHandler: () -> Int) {
self.numberOfItemsInSectionHandler = numberOfItemsInSectionHandler
self.cellForItemAtIndexPathHandler = cellForItemAtIndexPathHandler
self.numberOfSectionsHandler = numberOfSectionsHandler
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return numberOfSectionsHandler()
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return numberOfItemsInSectionHandler(section)
}
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
return cellForItemAtIndexPathHandler(collectionView, indexPath)! // Better not have the data source bridge outlive the data source itself.
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment