// // RegisterableView.swift // HSBC // // Created by Pierre Felgines on 09/08/16. // // import Foundation import UIKit // swiftlint:disable force_cast /* * Usage example: * * To register a cell class : * tableView.register(cell: .class(UITableViewCell.self)) * To register a cell nib : * tableView.register(cell: .nib(ADTableViewCell.self)) * * Note that there is a handy method tableView.register(cells: []) that allow * to register mutiple cells at once * * To dequeue a cell use : * let cell: UITableViewCell = tableView.dequeueCellAt(indexPath: indexPath) * * Same methods can be used on UITableView or UICollectionView. * */ public protocol ClassIdentifiable { static func identifier() -> String } extension NSObject: ClassIdentifiable { public static func identifier() -> String { return String(describing: self) } } public enum RegisterableView { case nib(NSObject.Type) case `class`(NSObject.Type) } public extension RegisterableView { @MainActor var nib: UINib? { switch self { case let .nib(cellClass): return UINib(nibName: String(describing: cellClass), bundle: nil) default: return nil } } var identifier: String { switch self { case let .nib(cellClass): return cellClass.identifier() case let .class(cellClass): return cellClass.identifier() } } var cellClass: AnyClass? { switch self { case let .class(cellClass): return cellClass default: return nil } } } @MainActor public protocol CollectionView { func register(cell: RegisterableView) func register(header: RegisterableView) func register(footer: RegisterableView) } public extension CollectionView { func register(cells: [RegisterableView]) { cells.forEach(register(cell:)) } func register(headers: [RegisterableView]) { headers.forEach(register(header:)) } func register(footers: [RegisterableView]) { footers.forEach(register(footer:)) } } extension UITableView: CollectionView { public func register(cell: RegisterableView) { switch cell { case .nib: register(cell.nib, forCellReuseIdentifier: cell.identifier) case .class: register(cell.cellClass, forCellReuseIdentifier: cell.identifier) } } public func register(header: RegisterableView) { switch header { case .nib: register(header.nib, forHeaderFooterViewReuseIdentifier: header.identifier) case .class: register(header.cellClass, forHeaderFooterViewReuseIdentifier: header.identifier) } } public func register(footer: RegisterableView) { register(header: footer) } } extension UICollectionView: CollectionView { public func register(cell: RegisterableView) { switch cell { case .nib: register(cell.nib, forCellWithReuseIdentifier: cell.identifier) case .class: register(cell.cellClass, forCellWithReuseIdentifier: cell.identifier) } } public func register(supplementaryView view: RegisterableView, kind: String) { switch view { case .nib: register(view.nib, forSupplementaryViewOfKind: kind, withReuseIdentifier: view.identifier) case .class: register(view.cellClass, forSupplementaryViewOfKind: kind, withReuseIdentifier: view.identifier) } } public func register(header: RegisterableView) { register(supplementaryView: header, kind: UICollectionView.elementKindSectionHeader) } public func register(footer: RegisterableView) { register(supplementaryView: footer, kind: UICollectionView.elementKindSectionFooter) } } extension UITableView { public func dequeueCell(_ cellClass: U.Type = U.self, at indexPath: IndexPath) -> U { return dequeueReusableCell(withIdentifier: U.identifier(), for: indexPath) as! U } public func dequeueHeader(_ headerClass: U.Type = U.self) -> U { return dequeueReusableHeaderFooterView(withIdentifier: U.identifier()) as! U } public func dequeueFooter(_ footerClass: U.Type = U.self) -> U { return dequeueHeader() } } extension UICollectionView { public func dequeueCell(_ cellClass: U.Type = U.self, at indexPath: IndexPath) -> U { return dequeueReusableCell(withReuseIdentifier: U.identifier(), for: indexPath) as! U } public func dequeueSupplementaryView(_ viewClass: U.Type = U.self, ofKind kind: String, at indexPath: IndexPath) -> U { return dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: U.identifier(), for: indexPath) as! U } public func dequeueHeader(_ headerClass: U.Type = U.self, at indexPath: IndexPath) -> U { return dequeueSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, at: indexPath) } public func dequeueFooter(_ footerClass: U.Type = U.self, at indexPath: IndexPath) -> U { return dequeueSupplementaryView(ofKind: UICollectionView.elementKindSectionFooter, at: indexPath) } }