通用UITableViewCell标识符

时间:2017-09-30 11:02:09

标签: ios swift uitableview generics reuseidentifier

我尝试使用类型和枚举而不是字符串作为cellIdentifier

我不想将单元格类名称用作标识符,因为我可以为一个类型单元格设置多个标识符(例如,不同表格视图中的基本单元格)

enum TableViewCellIdentifier: String {
    case formCell, questionCell

    // Here I can have the type, and I want to use it to ensure the cell dequeued by the identifier is the right type
    var typeCell: UITableViewCell.Type {
        switch self {
        case .formCell:
            return UITableViewCell.self
        case .questionCell:
            return QuestionCell.self
        }
    }

    // I could use an extension of UITableView to build an other version of dequeueCell,
    // but I'll choose after it the type constraint will let me choose.

    // Here I want to constraint the return type with the value of myValue.typeCell
    func dequeueCell(with tableView: UITableView, for indexPath: IndexPath) -> UITableViewCell {
        return tableView.dequeueReusableCell(withIdentifier: self.rawValue, for: indexPath)
    }
//    func dequeueCell<T: self.typeCell>(with tableView: UITableView, for indexPath: IndexPath) -> T {
//        return tableView.dequeueReusableCell(withIdentifier: self.rawValue, for: indexPath) as! T
//    }
}

任何想法?

谢谢!

1 个答案:

答案 0 :(得分:0)

import Foundation
import UIKit

protocol Reusable: class{
    static var reuseIdentifier: String { get }
}

extension Reusable {
    static var reuseIdentifier: String {
        return String(describing: self)

    }
}

extension UITableViewCell: Reusable{}
extension UITableViewHeaderFooterView: Reusable{}

protocol NibLoadableView {
    static var nibName: String { get }
}

extension NibLoadableView  {
    static var nibName: String {
        return String(describing: self)
    }
}

extension UITableViewCell: NibLoadableView {}

extension UITableView {

    func register<T: UITableViewCell>(_: T.Type)  {
        register(T.self, forCellReuseIdentifier: T.reuseIdentifier)
    }

    func registerNib<T: UITableViewCell>(_: T.Type)  {
        let bundle = Bundle(for: T.self)
        let nib = UINib(nibName: T.reuseIdentifier, bundle: bundle)
        print(T.nibName, T.reuseIdentifier)
        register(nib, forCellReuseIdentifier: T.reuseIdentifier)
    }

    func registerHeaderNib<T: UITableViewHeaderFooterView>(_: T.Type)  {
        let bundle = Bundle(for: T.self)
        let nib = UINib(nibName: T.reuseIdentifier, bundle: bundle)
        print(T.reuseIdentifier, T.reuseIdentifier)
        register(nib, forHeaderFooterViewReuseIdentifier: T.reuseIdentifier)
    }

    func dequeueReusableCell<T: UITableViewCell>(for indexPath: IndexPath) -> T  {
        print(T.reuseIdentifier)
        guard let cell = dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as? T else {
            fatalError("Could not dequeue cell with identifier: \(T.reuseIdentifier)")
        }
        return cell
    }

    func dequeueReusableHeaderFooterView<T: UITableViewHeaderFooterView>(for section: Int) -> T  {
        print(T.reuseIdentifier)
        guard let cell = dequeueReusableHeaderFooterView(withIdentifier: "DemoHeaderView") as? T else {
            fatalError("Could not dequeue cell with identifier: \(T.reuseIdentifier)")
        }
        return cell
    }

}

这是ViewContoller使用它的方式。

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.register(TestCell.self)

       let headerNib = UINib.init(nibName: "DemoHeaderView", bundle: Bundle.main)
       tableView.register(headerNib, forHeaderFooterViewReuseIdentifier: "DemoHeaderView")
        tableView.registerHeaderNib(DemoHeaderView.self)

    }



    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

    }  
}

extension ViewController: UITableViewDataSource, UITableViewDelegate {
    // MARK: - UITableView delegate
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 4
    }
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 100
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: TestCell = tableView.dequeueReusableCell(for: indexPath)
        cell.textLabel?.text  = "\(indexPath.row)"
        return cell
    }

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

        let headerView = tableView.dequeueReusableHeaderFooterView(for: section)


        return headerView
    }
}