UITableView所有已注册的类/笔尖

时间:2015-07-22 23:39:36

标签: ios uitableview

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

我想看看哪些已经在xib中自动注册(如果它是如何完成的),但是也可以看到任何手动注册也会很棒。

4 个答案:

答案 0 :(得分:13)

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

NSDictionary *registeredCellClasses = [tableView valueForKey:@"_cellClassDict"];
NSDictionary *registeredNibs = [tableView valueForKey:@"_nibMap"];

每个字典将注册的单元格重用标识符存储为键,将类名称/ Nib对象存储为值。

答案 1 :(得分:5)

<强>夫特

let registeredCellClasses = tableView.value(forKey: "_cellClassDict") as? [String:Any]
let registeredNibs = tableView.value(forKey: "_nibMap") as? [String:UINib]

答案 2 :(得分:3)

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 ?? [:]
}
}

答案 3 :(得分:0)

详情

  • Xcode 12.3 (12C33)
  • Swift 5.3

问题

使用 _nibMap_cellClassDict 可能不安全。 Apple 没有直接的 API 来获取注册单元。因此,基于 _nibMap_cellClassDict 的解决方案看起来像黑客。而且我们无法预测,Apple 是否会更改此 API。我建议自己制作 TableView 并在那里实现存储逻辑。

解决方案

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()
    }
}