Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save grzegorzkrukowski/93a4baecd61564f77d1762f0a4247c14 to your computer and use it in GitHub Desktop.
Save grzegorzkrukowski/93a4baecd61564f77d1762f0a4247c14 to your computer and use it in GitHub Desktop.
UITableView and UICollectionView extensions that allows to auto-register cells and extends both with simplified interfaces for dequeuing Edit
public protocol CellRegistration: class {
static var reuseIdentifier: String { get }
}
extension CellRegistration where Self: UIView {
public static var reuseIdentifier: String {
return String(describing: self)
}
}
extension UICollectionViewCell: CellRegistration { }
extension UITableViewCell: CellRegistration { }
private struct AssociatedObjectKey {
static var registeredCells = "registeredCells"
}
extension UITableView {
private var registeredCells: Set<String> {
get {
if objc_getAssociatedObject(self, &AssociatedObjectKey.registeredCells) as? Set<String> == nil {
self.registeredCells = Set<String>()
}
return objc_getAssociatedObject(self, &AssociatedObjectKey.registeredCells) as! Set<String>
}
set(newValue) {
objc_setAssociatedObject(self, &AssociatedObjectKey.registeredCells, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
public func register<T: UITableViewCell>(_: T.Type) where T: CellRegistration {
let bundle = Bundle(for: T.self)
if bundle.path(forResource: T.reuseIdentifier, ofType: "nib") != nil {
let nib = UINib(nibName: T.reuseIdentifier, bundle: bundle)
register(nib, forCellReuseIdentifier: T.reuseIdentifier)
} else {
register(T.self, forCellReuseIdentifier: T.reuseIdentifier)
}
}
public func dequeueReusableCell<T: UITableViewCell>(forIndexPath indexPath: IndexPath) -> T where T: CellRegistration {
if self.registeredCells.contains(T.reuseIdentifier) == false {
self.registeredCells.insert(T.reuseIdentifier)
self.register(T.self)
}
guard let cell = dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as? T else {
fatalError("Error dequeuing cell with reuse identifier: \(T.reuseIdentifier)")
}
return cell
}
}
extension UICollectionView {
private var registeredCells: Set<String> {
get {
if objc_getAssociatedObject(self, &AssociatedObjectKey.registeredCells) as? Set<String> == nil {
self.registeredCells = Set<String>()
}
return objc_getAssociatedObject(self, &AssociatedObjectKey.registeredCells) as! Set<String>
}
set(newValue) {
objc_setAssociatedObject(self, &AssociatedObjectKey.registeredCells, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
public func register<T: UITableViewCell>(_: T.Type) where T: CellRegistration {
let bundle = Bundle(for: T.self)
if bundle.path(forResource: T.reuseIdentifier, ofType: "nib") != nil {
let nib = UINib(nibName: T.reuseIdentifier, bundle: bundle)
register(nib, forCellWithReuseIdentifier: T.reuseIdentifier)
} else {
register(T.self, forCellWithReuseIdentifier: T.reuseIdentifier)
}
}
public func dequeueReusableCell<T: UITableViewCell>(forIndexPath indexPath: IndexPath) -> T where T: CellRegistration {
if self.registeredCells.contains(T.reuseIdentifier) == false {
self.registeredCells.insert(T.reuseIdentifier)
self.register(T.self)
}
guard let cell = dequeueReusableCell(withReuseIdentifier: T.reuseIdentifier, for: indexPath) as? T else {
fatalError("Error dequeuing cell with reuse identifier: \(T.reuseIdentifier)")
}
return cell
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment