Forked from grzegorzkrukowski/UITableView+Registration.swift
Created
December 20, 2018 07:59
-
-
Save hslatman/2f893ec27b696facc32d776af550f267 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
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 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