简化 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
中的register
和deque
以及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
注意:正如您所要求的,我将 UITableViewCell
s 存储到单元格数组中并完成我的工作。尽管我们的实现有细微的变化,但我希望这会有所帮助。
【讨论】:
【参考方案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 单元格的函数简化 tableview 代码
使用 UITapGestureRecognizer 检测 UITableViewCell 中 UILabel 的点击事件