dequeueするタイミングでregisterしてなかったら自動でregisterすれば良くない?って思ったので実装してみた。
XIBとクラスを一緒にして型名でregister/dequeueしていること前提です。
public extension UITableView {
func register<T: UITableViewCell>(_ cellType: T.Type) {
let className = cellType.className
let nib = UINib(nibName: className, bundle: nil)
register(nib, forCellReuseIdentifier: className)
}
func dequeue<T: UITableViewCell>(_ cellType: T.Type, indexPath: IndexPath) -> T {
return dequeueReusableCell(withIdentifier: cellType.className, for: indexPath) as! T
}
}
var AssociatedObjectHandle: UInt8 = 0
public extension UITableView {
var registeredClasses: [UITableViewCell.Type] {
get { return ((objc_getAssociatedObject(self, &AssociatedObjectHandle) ?? 0) as? [UITableViewCell.Type]) ?? [] }
set { objc_setAssociatedObject(self, &AssociatedObjectHandle, newValue, .OBJC_ASSOCIATION_RETAIN) }
}
public func retrieve<T: UITableViewCell>(_ cellType: T.Type, indexPath: IndexPath) -> T {
if !registeredClasses.contains(where: { $0 === cellType }) {
register(cellType)
registeredClasses.append(cellType)
}
return dequeue(cellType, indexPath: indexPath)
}
}
使う時は
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.retrieve(CustomTableViewCell.self, indexPath: indexPath)
return cell
}
UITableViewにregisterする必要はありません。
解説
retrieveを呼んだタイミングでregisterしていなければしているだけ
まとめ
実装してみたもののcellAtRowのパフォーマンスに影響無いか不安(あっても初回だけだと思うけど)
どうなんだろうなぁこの実装
あとretrieve
はもっと良い名前ありそう