如何使用外部数据源转换单元格类型

How to Cast Cell Type with External DataSource

我有以下用于各种 tableView 的外部数据源。

我想让它动态化,并能够将 CellConfigurator 中的 UITableViewCell 投射到各种自定义单元格。我为下面的每个模型做了一个扩展。但我需要能够转换为扩展中的不同单元格类型。

import UIKit

class ProductSearchDataSource<Model>: NSObject, UITableViewDataSource {

    typealias CellConfigurator = (Model, UITableViewCell) -> Void

    var models: [Model]

    private let reuseIdentifier: String
    private let cellConfigurator: CellConfigurator

    init(models: [Model], reuseIdentifier: String, cellConfigurator: @escaping CellConfigurator) {
        self.models = models
        self.reuseIdentifier = reuseIdentifier
        self.cellConfigurator = cellConfigurator
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return models.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let model = models[indexPath.row]
        let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath)
        cellConfigurator(model, cell)
        return cell
    }
}

extension ProductSearchDataSource where Model == ProductSearchHistory {
    static func make(for productSearch: [ProductSearchHistory], reuseIdentifier: String = "productSearchTableViewCell") -> ProductSearchDataSource {
        return ProductSearchDataSource(models: productSearch, reuseIdentifier: reuseIdentifier) { (productSearch, productSearchTableViewCell) in
            productSearchTableViewCell.textLabel?.text = productSearch.searchHistory
        }
    }
}

您需要为单元格引入额外的占位符类型:

class ProductSearchDataSource<Model, Cell: UITableViewCell>: NSObject, UITableViewDataSource {

    typealias CellConfigurator = (Model, Cell) -> Void

    ...

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let model = models[indexPath.row]
        // Note: You may want to handle the downcast better...
        let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! Cell
        cellConfigurator(model, cell)
        return cell
    }
}

extension ProductSearchDataSource where Model == ProductSearchHistory, Cell == ProductSearchCell {
    static func make(for productSearch: [ProductSearchHistory], reuseIdentifier: String = "productSearchTableViewCell") -> ProductSearchDataSource {
        return ProductSearchDataSource(models: productSearch, reuseIdentifier: reuseIdentifier) { (productSearch, productSearchTableViewCell) in
            // `productSearchTableViewCell` will now have a type of `ProductSearchCell `.
            productSearchTableViewCell.textLabel?.text = productSearch.searchHistory
        }
    }
}