Typed UITableView & UICollectionView Dequeuing in Swift
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
import UIKit | |
extension UICollectionReusableView { | |
/// The default implementation of `defaultIdentifier()` uses `NSStringFromClass(class)` rather than `String(class)` so that the module name is includded. | |
/// The hope being that this makes collisions unlikely making it unnnecessary to provide your own implementations. | |
public class func defaultIdentifier() -> String { | |
return NSStringFromClass(self) | |
} | |
} | |
// MARK: - Cell Registration | |
public extension UICollectionView { | |
public func register<T: UICollectionViewCell>(cellClass `class`: T.Type) { | |
registerClass(`class`, forCellWithReuseIdentifier: `class`.defaultIdentifier()) | |
} | |
public func register<T: UICollectionViewCell>(nib: UINib, forClass `class`: T.Type) { | |
registerNib(nib, forCellWithReuseIdentifier: `class`.defaultIdentifier()) | |
} | |
/** | |
Dequeue a Reusable Cell in a way that provides type information. | |
This call will raise a fatal error if the cell was not registered with `defaultIdentifier()` this behaviour is not particularily different from the method which it is covering, | |
`dequeueReusableCellWithReuseIdentifier` which will raise an NSInternalInconsistency Exception because the cell was not registered with the corrrect identifier. If you are going to use this | |
dequeue method it is recomended that you use `register<T: UICollectionViewCell>(cellClass: T.Type)` or `register<T: UICollectionViewCell>(nib: UINib, forClass: T.Type)` for registration. | |
- parameter `class`: The class whose type you are dequeing. | |
- parameter indexPath: The index path of the cell you want to dequeue. | |
- returns: Returns a cell of the type requested. | |
*/ | |
public func dequeueReusableCell<T: UICollectionViewCell>(withClass `class`: T.Type, forIndexPath indexPath: NSIndexPath) -> T { | |
guard let cell = dequeueReusableCellWithReuseIdentifier(`class`.defaultIdentifier(), forIndexPath: indexPath) as? T else { | |
fatalError("Error: cell with identifier: \(`class`.defaultIdentifier()) for index path: \(indexPath) is not \(T.self)") | |
} | |
return cell | |
} | |
} | |
// MARK: - Supplementary View Registration | |
public extension UICollectionView { | |
public func register<T: UICollectionReusableView>(viewClass `class`: T.Type, forSupplementaryViewOfKind kind: String) { | |
registerClass(`class`, forSupplementaryViewOfKind: kind, withReuseIdentifier: `class`.defaultIdentifier()) | |
} | |
public func register<T: UICollectionReusableView>(nib: UINib, forSupplementaryViewOfKind kind: String, withClass `class`: T.Type) { | |
registerNib(nib, forSupplementaryViewOfKind: kind, withReuseIdentifier: `class`.defaultIdentifier()) | |
} | |
/** | |
Dequeue a Supplementary View in a way that provides type information. | |
This call will raise a fatal error if the view was not registered with `defaultIdentifier()` this behaviour is not particularily different from the method which it is covering, | |
`dequeueReusableSupplementaryViewOfKind` which will raise an NSInternalInconsistency Exception because the cell was not registered with the corrrect identifier. If you are going to use this | |
dequeue method it is recomended that you use `register<T: UICollectionReusableView>(viewClass: T.Type, forSupplementaryViewOfKind: String)` or | |
`register<T: UICollectionReusableView>(nib: UINib, forSupplementaryViewOfKind: String, withClass: T.Type)` for registration. | |
- parameter `class`: The class whose type you are dequeing. | |
- parameter kind: The supplementary view Kind you are dequeing. | |
- parameter indexPath: The index path of the cell you want to dequeue. | |
- returns: Returns a view of the type requested. | |
*/ | |
public func dequeueReusableSupplementaryView<T: UICollectionReusableView>(withClass `class`: T.Type, ofKind kind: String, forIndexPath indexPath: NSIndexPath) -> T { | |
guard let supplement = dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: `class`.defaultIdentifier(), forIndexPath: indexPath) as? T else { | |
fatalError("Error: supplementary view with identifier: \(`class`.defaultIdentifier()) for index path: \(indexPath) is not \(T.self)") | |
} | |
return supplement | |
} | |
} |
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
import UIKit | |
extension UITableViewCell { | |
/// The default implementation of `defaultIdentifier()` uses `NSStringFromClass(class)` rather than `String(class)` so that the module name is includded. | |
/// The hope being that this makes collisions unlikely making it unnnecessary to provide your own implementations. | |
public class func defaultIdentifier() -> String { | |
return NSStringFromClass(self) | |
} | |
} | |
extension UITableViewHeaderFooterView { | |
/// The default implementation of `defaultIdentifier()` uses `NSStringFromClass(class)` rather than `String(class)` so that the module name is includded. | |
/// The hope being that this makes collisions unlikely making it unnnecessary to provide your own implementations. | |
public class func defaultIdentifier() -> String { | |
return NSStringFromClass(self) | |
} | |
} | |
// MARK: - Cell Registration | |
extension UITableView { | |
public func register<T: UITableViewCell>(cellClass `class`: T.Type) { | |
registerClass(`class`, forCellReuseIdentifier: `class`.defaultIdentifier()) | |
} | |
public func register<T: UITableViewCell>(nib: UINib, forClass `class`: T.Type) { | |
registerNib(nib, forCellReuseIdentifier: `class`.defaultIdentifier()) | |
} | |
/** | |
Dequeue a Reusable Cell in a way that provides type information. | |
If you are going to use this dequeue method it is recomended that you use `register<T: UITableViewCell>(cellClass: T.Type)` or | |
`register<T: UITableViewCell>(nib: UINib, forClass: T.Type)` for registration. | |
- parameter `class`: The class whose type you are dequeing. | |
- returns: Returns a view of the type requested if it was registered, `nil` otherwise. | |
*/ | |
public func dequeueReusableCell<T: UITableViewCell>(withClass `class`: T.Type) -> T? { | |
return dequeueReusableCellWithIdentifier(`class`.defaultIdentifier()) as? T | |
} | |
/** | |
Dequeue a Reusable Cell in a way that provides type information. | |
This call will raise a fatal error if the cell was not registered with `defaultIdentifier()` this behaviour is not particularily different from the method which it is covering, | |
`dequeueReusableCellWithIdentifier` which will raise an NSInternalInconsistency Exception because the cell was not registered with the corrrect identifier or at all. If you are going to use this | |
dequeue method it is recomended that you use `register<T: UITableViewCell>(cellClass: T.Type)` or `register<T: UITableViewCell>(nib: UINib, forClass: T.Type)` for registration. | |
- parameter `class`: The class whose type you are dequeing. | |
- parameter indexPath: The index path of the cell you want to dequeue. | |
- returns: Returns a cell of the type requested. | |
*/ | |
public func dequeueReusableCell<T: UITableViewCell>(withClass `class`: T.Type, forIndexPath indexPath: NSIndexPath) -> T { | |
guard let cell = dequeueReusableCellWithIdentifier(`class`.defaultIdentifier(), forIndexPath: indexPath) as? T else { | |
fatalError("Error: cell with identifier: \(`class`.defaultIdentifier()) for index path: \(indexPath) is not \(T.self)") | |
} | |
return cell | |
} | |
} | |
// MARK: - Supplementary View Registration | |
extension UITableView { | |
public func register<T: UITableViewHeaderFooterView>(headerFooterClass `class`: T.Type) { | |
registerClass(`class`, forHeaderFooterViewReuseIdentifier: `class`.defaultIdentifier()) | |
} | |
public func register<T: UITableViewHeaderFooterView>(nib: UINib, forHeaderFooterClass `class`: T.Type) { | |
registerNib(nib, forHeaderFooterViewReuseIdentifier: `class`.defaultIdentifier()) | |
} | |
/** | |
Dequeue a Header/Footer View in a way that provides type information. | |
If you are going to use this dequeue method it is recomended that you use `register<T: UITableViewHeaderFooterView>(headerFooterClass `class`: T.Type)` or | |
`register<T: UITableViewHeaderFooterView>(nib: UINib, forHeaderFooterClass `class`: T.Type)` for registration. | |
- parameter `class`: The class whose type you are dequeing. | |
- returns: Returns a view of the type requested if it was registered, `nil` otherwise. | |
*/ | |
public func dequeueResuableHeaderFooterView<T: UITableViewHeaderFooterView>(withClass `class`: T.Type) -> T? { | |
return dequeueReusableHeaderFooterViewWithIdentifier(`class`.defaultIdentifier()) as? T | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Zev Eisenberg posted that you can use
To get a nice readable nav for your default identifiers, even from generic cells.