Created
March 9, 2017 01:15
-
-
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
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