Ios UITable查看所有注册的类/NIB

Ios UITable查看所有注册的类/NIB,ios,uitableview,Ios,Uitableview,如何查看已注册的类和/或NIB及其单元标识符 我想看看哪些已在xib中自动注册(如果是这样做的话),但能够看到任何手动注册的也很好。UITableView将有关已注册的单元格类和NIB的信息存储在单独的字典中,您可以使用KVC和私有属性密钥获取这些信息: NSDictionary *registeredCellClasses = [tableView valueForKey:@"_cellClassDict"]; NSDictionary *registeredNibs = [tableView

如何查看已注册的类和/或NIB及其单元标识符


我想看看哪些已在xib中自动注册(如果是这样做的话),但能够看到任何手动注册的也很好。

UITableView将有关已注册的单元格类和NIB的信息存储在单独的字典中,您可以使用KVC和私有属性密钥获取这些信息:

NSDictionary *registeredCellClasses = [tableView valueForKey:@"_cellClassDict"];
NSDictionary *registeredNibs = [tableView valueForKey:@"_nibMap"];
每个字典将注册的单元重用标识符存储为键,将类名/Nib对象存储为值。

Swift

let registeredCellClasses = tableView.value(forKey: "_cellClassDict") as? [String:Any]
let registeredNibs = tableView.value(forKey: "_nibMap") as? [String:UINib]
细节
  • 代码12.3(12C33)
  • Swift 5.3
问题 使用
\u nibMap
\u cellClassDict
可能不安全。苹果还没有直接的API来获取注册的细胞。因此,基于
\u nibMap
\u cellClassDict
的解决方案看起来像黑客。我们无法预测,苹果是否会改变这个API。我建议自己制作
TableView
,并在那里实现存储逻辑

解决方案
你打算怎么处理这些信息?只是为了兴趣/调试吗?@Wain只是为了调试。当我在验证我的故事板设置是否正确方面遇到问题时,我需要这个。如果你想测试某个单元格是否在某个表视图中注册,它也可以用于单元测试。对collectionview有什么想法吗?@MichaelOzeryansky:我想他只是想展示另一种方法。我知道这是一种更适合生产的解决方案,但最初我只是为了调试。你有一个有趣的模板。
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 ?? [:]
}
}
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) {}
}
// 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()
    }
}