我尝试使用类型和枚举而不是字符串作为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
// }
}
任何想法?
谢谢!
答案 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
}
}