How can I view already registered classes and/or nibs and their cell identifier?
I would like to see which have been automatically registered within the xib (if that's how it's done), but also being able to see any manually registered would be great too.
Swift
let registeredCellClasses = tableView.value(forKey: "_cellClassDict") as? [String:Any]
let registeredNibs = tableView.value(forKey: "_nibMap") as? [String:UINib]
Usage of the _nibMap
and _cellClassDict
may be not safe. Apple has not direct API to get registered cells. So, solutions based on _nibMap
and _cellClassDict
looks like hacks. And we can not predict, will Apple change this API or not. I suggest to make own TableView
and implement storing logic there.
class TableView: UITableView {
private (set) lazy var registeredCellIdentifiers = Set<String>()
func register(nib: UINib?, forCellReuseIdentifier identifier: String) {
super.register(nib, forCellReuseIdentifier: identifier)
registeredCellIdentifiers.insert(identifier)
}
func register(nib: UINib?, forHeaderFooterViewReuseIdentifier identifier: String) {
super.register(nib, forHeaderFooterViewReuseIdentifier: identifier)
registeredCellIdentifiers.insert(identifier)
}
func register(cellClass: AnyClass?, forCellReuseIdentifier identifier: String) {
super.register(cellClass, forCellReuseIdentifier: identifier)
registeredCellIdentifiers.insert(identifier)
}
func register(aClass: AnyClass?, forHeaderFooterViewReuseIdentifier identifier: String) {
super.register(aClass, forHeaderFooterViewReuseIdentifier: identifier)
registeredCellIdentifiers.insert(identifier)
}
@available(*, deprecated, message: "use register(nib: UINib?, forCellReuseIdentifier identifier: String) instead")
override func register(_ nib: UINib?, forCellReuseIdentifier identifier: String) {}
@available(*, deprecated, message: "use register(nib: UINib?, forCellReuseIdentifier identifier: String) instead")
override func register(_ nib: UINib?, forCellReuseIdentifier identifier: String) {}
@available(*, deprecated, message: "use register(nib: UINib?, forHeaderFooterViewReuseIdentifier identifier: String) instead")
override func register(_ nib: UINib?, forHeaderFooterViewReuseIdentifier identifier: String) { }
@available(*, deprecated, message: "ude register(cellClass: AnyClass?, forCellReuseIdentifier identifier: String) instead")
override func register(_ cellClass: AnyClass?, forCellReuseIdentifier identifier: String) {}
@available(*, deprecated, message: "use register(aClass: AnyClass?, forHeaderFooterViewReuseIdentifier identifier: String) instead")
override func register(_ aClass: AnyClass?, forHeaderFooterViewReuseIdentifier identifier: String) {}
}
Do not forget to paste here code defined above
// MARK: - Auto Generated identifiers
protocol Identifiable: class {
static var identifier: String { get }
}
extension Identifiable {
static var identifier: String { "\(self)" }
}
// MARK: - Define Cells
class TableViewCell: UITableViewCell, Identifiable {
var mainBackgroundColor: UIColor { .white }
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
backgroundColor = mainBackgroundColor
}
@available(*, deprecated, message: "")
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
class GreenCell: TableViewCell {
override var mainBackgroundColor: UIColor { .green }
}
class OrangeCell: TableViewCell {
override var mainBackgroundColor: UIColor { .orange }
}
// MARK: ViewController
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let tableView = TableView()
view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
tableView.register(cellClass: GreenCell.self, forCellReuseIdentifier: GreenCell.identifier)
tableView.register(cellClass: OrangeCell.self, forCellReuseIdentifier: OrangeCell.identifier)
tableView.dataSource = self
print(tableView.registeredCellIdentifiers)
}
}
// MARK: - UITableViewDataSource
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int { 1 }
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 10 }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let identifier = (indexPath.row % 2) == 0 ? GreenCell.identifier : OrangeCell.identifier
return tableView.dequeueReusableCell(withIdentifier: identifier) ?? UITableViewCell()
}
}
UITableView stores information about registered cell classes and nibs in separate dictionaries, which you can get using KVC and private property keys:
NSDictionary *registeredCellClasses = [tableView valueForKey:@"_cellClassDict"];
NSDictionary *registeredNibs = [tableView valueForKey:@"_nibMap"];
Each dictionary stores registered cell reuse identifiers as keys and class names/Nib objects as values.
extension UITableView {
var registeredNibs: [String: UINib] {
let dict = value(forKey: "_nibMap") as? [String: UINib]
return dict ?? [:]
}
var registeredClasses: [String: Any] {
let dict = value(forKey: "_cellClassDict") as? [String: Any]
return dict ?? [:]
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With