使用共享数据源但行数不同的多个表视图

Multiple tableviews using a shared datasource but varying number of rows

我的应用程序中有几个表格视图使用一个名为 TaskListDataSource class 的数据源实例,它符合 UITableViewDataSource

class TaskListDataSource: NSObject {
    typealias TaskCompletedAction = () -> Void
    
    private var tasks: [Task] = SampleData.tasks
    private var taskCompletedAction: TaskCompletedAction?
    
    init(taskCompletedAction: @escaping TaskCompletedAction) {
        self.taskCompletedAction = taskCompletedAction
        super.init()
    }
}

extension TaskListDataSource: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return tasks.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "taskCell", for: indexPath) as? TaskCell else {
            fatalError("Unable to dequeue TaskCell")
        }
        cell.configure(task: tasks[indexPath.row]) {
            self.tasks[indexPath.row].completed.toggle()
            self.taskCompletedAction?()
        }
        return cell
    }
}

我通过依赖注入传入实例并像这样设置表视图数据源。我为所有使用此数据源对象的视图控制器执行此操作。

var taskListDataSource: TaskListDataSource
    
init?(coder: NSCoder, taskListDataSource: TaskListDataSource) {
    self.taskListDataSource = taskListDataSource
    super.init(coder: coder)
}
    
required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.register(UINib(nibName: "TaskCell", bundle: nil), forCellReuseIdentifier: "taskCell")
    tableView.dataSource = taskListDataSource
}

但是我想实现一种方法,以便在其中一个 UITableViewController 上将行数限制为 3 行。目前,由于以下代码片段,它将始终只显示任务数组中的任务总数。

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

在每个 tableview 上它显示了任务的总数,但我想要一种方法可以以某种方式保持 cellForRowAt 函数的可重用性但使 numberOfRows 函数动态化。

你可以添加一个字典来保存每个tableview的限制

    ...
    private maxRows: [String: Int?] = [:]
    ...

添加一个函数来处理绑定数据源

    ...
    func add(_ tableView: UITableView, maxRows: Int? = nil) {
        if let id = tableView.id {
            self.maxRows[id] = maxRows
        }
        tableView.datasource = self
    }
    ...

然后数据源函数 numberOfRowsInSection 变为

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if let id = tableView.id {
              return maxRows[id] ?? tasks.count
        }
        return tasks.count
}

并将表视图数据源设置为

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.register(UINib(nibName: "TaskCell", bundle: nil), forCellReuseIdentifier: "taskCell")
    taskListDataSource.add(tableView, maxRow: 3) 
}

tableView.id可以是任何你想要的。例如:您将 UITableView 子类化并添加一个 属性

class UITableViewWithID: UITableView {
    var id: String?
}