简化 TableView 中的 cellForRowAt

Posted

技术标签:

【中文标题】简化 TableView 中的 cellForRowAt【英文标题】:Simplifying cellForRowAt in TableView 【发布时间】:2020-05-19 16:21:51 【问题描述】:

我正在编写一个个人 ios 应用程序来跟踪一些事情。我的应用程序运行良好,但我将注意力转向整理代码和清理工作。在我的 tableview 中,其中一个单元格是 uicollectionview,根据我选择的 collectionviewcell,自定义 tableviewcell 会加载到同一个表中。此时,我的 collectionview 中有大约十几个项目,我可以从中选择,然后从大约十几个不同的 tableviewcells 中选择一个来加载。每个单元收集不同的信息位。

一切都按我的预期工作,但我不喜欢在整个 tableviewcontroller 中,我有许多基于我必须处理的 tableviewcells 的重复部分

override func viewDidLoad() 
    super.viewDidLoad()
    // register the various tablecells
    tableView.register(UINib(nibName: "eventO2TableViewCell", bundle: nil), forCellReuseIdentifier: "eventO2TableViewCell")
...
    tableView.register(UINib(nibName: "eventTmpTableViewCell", bundle: nil), forCellReuseIdentifier: "eventTmpTableViewCell")
    tableView.register(UINib(nibName: "eventDXTableViewCell", bundle: nil), forCellReuseIdentifier: "eventDXTableViewCell")

同样的 cellForRowAt 非常大(即一个 switch 语句,十几个 case ,每个都有一个对应的

switch selectedIndexPath.row  // the index of the uicollectionviewcell
case 1:
    let cell = tableView.dequeueReusableCell(withIdentifier: "eventTmpTableViewCell", for: indexPath) as! eventTmpTableViewCell
    return cell
...
case 11:
    let cell = tableView.dequeueReusableCell(withIdentifier: "eventO2TableViewCell", for: indexPath) as! eventO2TableViewCell
    return cell
default:
    let cell = tableView.dequeueReusableCell(withIdentifier: "eventDXTableViewCell", for: indexPath) as! eventDXTableViewCell
    return cell

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) 

另一个带有十几个案例评估的 switch 语句来确定使用了哪个单元格并提取我需要保存的信息。

正在考虑在类似问题Is it possible to store custom UITableViewCell into Array? 中提出的想法,但好奇是否有其他建议?仍然认为自己是这个领域的初学者。谢谢

【问题讨论】:

也许这会对你有所帮助:medium.com/chili-labs/… 非常感谢您,我将查看 Medium 文章,看看如何最好地适应我的设置... 【参考方案1】:

我为UITableView 中的registerdeque 以及UITableViewCell 中的identifier 创建了扩展,这里是一些示例代码:

UITableViewExtension.swift

public extension UITableView 

    func register<CellClass: UITableViewCell>(_ cellClass: CellClass.Type) 
        register(cellClass, forCellReuseIdentifier: cellClass.identifier)
    

    func dequeue<CellClass: UITableViewCell>(
        _ cellClass: CellClass.Type,
        for indexPath: IndexPath,
        setup: ((CellClass) -> Void)? = nil) -> UITableViewCell 
        let cell = dequeueReusableCell(withIdentifier: cellClass.identifier, for: indexPath)
        if let cell = cell as? CellClass 
            setup?(cell)
        
        return cell
    

UITableViewCell.swift

extension UITableViewCell 
    static var identifier: String 
        return String(describing: self)
    

然后在 ViewController.swift 中

class Cell1: UITableViewCell 
    // ...

class Cell2: UITableViewCell 
    // ...


class ViewController: UITableViewController 

    override func viewDidLoad() 
        super.viewDidLoad()

        let cells = [Cell1.self, Cell2.self]
        tableView.register(cells)
    

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        return tableView.dequeue(Cell1.self, for: indexPath)  cell in
            // customise cell
        
    

注意:正如您所要求的,我将 UITableViewCells 存储到单元格数组中并完成我的工作。尽管我们的实现有细微的变化,但我希望这会有所帮助。

【讨论】:

【参考方案2】:

您可以创建一个协议DequeueInitializable 并像这样编写它的扩展

import Foundation
import UIKit

protocol DequeueInitializable 
    static var reuseableIdentifier: String  get 


extension DequeueInitializable where Self: UITableViewCell 

    static var reuseableIdentifier: String 
        return String(describing: Self.self)
    

    static func dequeue(tableView: UITableView) -> Self 
        guard let cell = tableView.dequeueReusableCell(withIdentifier: self.reuseableIdentifier) else 
            return UITableViewCell() as! Self
        
        return cell as! Self
    
    static func register(tableView: UITableView)  
        let cell = UINib(nibName: self.reuseableIdentifier, bundle: nil)
        tableView.register(cell, forCellReuseIdentifier: self.reuseableIdentifier)
    

然后在你的单元类中你确认该协议

class Cell1: UITableViewCell, DequeueInitializable  
class Cell2: UITableViewCell, DequeueInitializable  

现在您可以轻松注册和出列单元格

return Cell1.dequeue(tableView: tableView)

注册

Cell1.register(tableView: tableView)

【讨论】:

以上是关于简化 TableView 中的 cellForRowAt的主要内容,如果未能解决你的问题,请参考以下文章

简化 TableView 中的 cellForRowAt

Tableview 单元格可重用性,切割标签文本

如何在 UITableViewCell 中添加多行

UITableViewCell 未按预期显示约束

使用调用自定义 tableview 单元格的函数简化 tableview 代码

使用 UITapGestureRecognizer 检测 UITableViewCell 中 UILabel 的点击事件