引言
日常码UI时是不是经常遇到这些情况?
- 项目 run 起来后发现崩溃了😱,查看控制台输出发现 cell 忘记注册了😂
- 注册代码不知道放在哪里合适🤔,跟复用代码很分裂
想一下,在复用cell时自动注册,上面的问题是不是都解决了
话不多说直接上代码🕶️
UITableView实现
import UIKit
private var kCellRegisterTable: Void?
private var kHeaderFooterRegisterTable: Void?
// MARK: 注册复用
extension NameSpace where Base: UITableView {
/// 免注册复用cell,未注册时会自动注册,并记录到cellRegisterTable
public func dequeueCell<T: UITableViewCell>(_ className: T.Type, for indexPath: IndexPath) -> T {
let identifier = String(describing: className)
if !base.cellRegisterTable.contains(identifier) {
register(cell: className)
}
guard let cell = base.dequeueReusableCell(withIdentifier: identifier, for: indexPath) as? T else {
assertionFailure("Couldn't find UITableViewCell for \(identifier)")
return T(style: .default, reuseIdentifier: identifier)
}
return cell
}
/// 免注册复用header footer view,未注册时会自动注册,并记录到headerFooterRegisterTable
public func dequeueHeaderFooter<T: UITableViewHeaderFooterView>(_ className: T.Type) -> T {
let identifier = String(describing: className)
if !base.headerFooterRegisterTable.contains(identifier) {
register(headerFooter: className)
}
guard let headerFooterView = base.dequeueReusableHeaderFooterView(withIdentifier: identifier) as? T else {
assertionFailure("Couldn't find UITableViewHeaderFooterView for \(identifier)")
return T(reuseIdentifier: identifier)
}
return headerFooterView
}
/// 注册header footer view,记录到headerFooterRegisterTable
public func register<T: UITableViewHeaderFooterView>(headerFooter className: T.Type) {
let identifier = String(describing: className)
base.headerFooterRegisterTable.insert(identifier)
base.register(T.self, forHeaderFooterViewReuseIdentifier: identifier)
}
/// 注册cell,记录到cellRegisterTable
public func register<T: UITableViewCell>(cell className: T.Type) {
let identifier = String(describing: className)
base.cellRegisterTable.insert(identifier)
base.register(T.self, forCellReuseIdentifier: identifier)
}
}
private extension UITableView {
var cellRegisterTable: Set<String> {
get {
if let table = objc_getAssociatedObject(self, &kCellRegisterTable) as? Set<String> {
return table
} else {
objc_setAssociatedObject(self, &kCellRegisterTable, Set<String>(), .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return []
}
}
set {
objc_setAssociatedObject(self, &kCellRegisterTable, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
var headerFooterRegisterTable: Set<String> {
get {
if let table = objc_getAssociatedObject(self, &kHeaderFooterRegisterTable) as? Set<String> {
return table
} else {
objc_setAssociatedObject(self, &kHeaderFooterRegisterTable, Set<String>(), .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return []
}
}
set {
objc_setAssociatedObject(self, &kHeaderFooterRegisterTable, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
UICollectionView实现
自己动手试试吧