何时使用dequeueReusableCellWithIdentifier与dequeueReusableCellWithIdentifier:forIndexPath
有两个重载dequeueReusableCellWithIdentifier,我试图确定何时应该使用一个vs其他?
有关forIndexPath函数的apple文档声明: “此方法使用索引path根据表格视图中单元格的位置执行其他configuration。”
我不知道如何解释,但?
最重要的区别是,如果您没有为标识符注册类或笔尖, forIndexPath:
版本会断言(崩溃)。 在这种情况下,较旧的(非forIndexPath:
版本返回nil
。
通过发送registerClass:forCellReuseIdentifier:
到表视图注册一个类的标识符。 通过发送registerNib:forCellReuseIdentifier:
给表格视图registerNib:forCellReuseIdentifier:
一个标识符。
如果在故事板中创build表格视图和单元格原型,则故事板加载器将注册您在故事板中定义的单元格原型。
第200场会议 – 来自WWDC 2012的Cocoa Touch的新特性讨论了从8月30日开始的(当时新的) forIndexPath:
版本。 它说“你将永远得到一个初始化的单元格”(没有提到它会崩溃,如果你没有注册类或笔尖)。
该video还说,“这将是正确的大小,索引path”。 大概这意味着它将在返回之前设置单元格的大小,通过查看表视图的自身宽度并调用委托的tableView:heightForRowAtIndexPath:
方法(如果已定义)。 这就是为什么它需要索引path。
dequeueReusableCellWithIdentifier:forIndexPath:
将始终返回一个单元格。 它要么使用现有的单元格,要么创build一个新的单元格,并在没有单元格时返回。
而传统的dequeueReusableCellWithIdentifier:
将返回一个单元格,如果存在的话,如果有一个单元格可以被重用,则返回否则返回nil。 所以你必须写一个条件来检查nil
值。
要回答你的问题,请使用dequeueReusableCellWithIdentifier:
当你想支持iOS 5及更低版本,因为dequeueReusableCellWithIdentifier:forIndexPath
仅适用于iOS 6+
参考: https : //developer.apple.com/library/ios/documentation/uikit/reference/UITableView_Class/Reference/Reference.html#//apple_ref/occ/instm/UITableView/dequeueReusableCellWithIdentifier : forIndexPath :
我从来没有理解为什么苹果创build了更新的方法,dequeueReusableCellWithIdentifier:forIndexPath :. 他们的文件不完整,有些误导。 我已经能够区分这两种方法的唯一区别是,旧的方法可以返回零,如果它没有find一个传入标识符的单元格,而较新的方法崩溃,如果它不能返回一个小区。 如果你已经正确设置了标识符,那么这两种方法都能保证返回一个单元格,并使单元格成为一个故事板。 如果你注册一个类或xib,并且使你的单元格在代码或xib文件中,这两种方法也可以保证返回一个单元格。
如果您使用dynamic生成的内容,我会build议使用两者。 否则你的应用程序可能会意外崩溃。 您可以实现自己的function来检索可选的可重用单元格。 如果它是nil
你应该返回一个空的单元格是不可见的:
Swift 3
// Extensions to UITableView extension UITableView { // returns nil, if identifier does not exist. // Otherwise it returns a configured cell for the given index path open func tryDequeueReusableCell ( withIdentifier identifier: String, for indexPath: IndexPath) -> UITableViewCell? { let cell = self.dequeueReusableCell(withIdentifier: identifier) if cell != nil { return self.dequeueReusableCell(withIdentifier: identifier, for: indexPath) } return nil } }
而扩展返回一个空单元格:
// Extension to UITableViewCell extension UITableViewCell { // Generates an empty table cell that is not visible class func empty() -> UITableViewCell { let emptyCell = UITableViewCell(frame:CGRect(x:0, y:0, width:0, height:0)) emptyCell.backgroundColor = UIColor.clear return emptyCell } }
如何使用它的完整示例:
import Foundation import UIKit // A protocol is used to identify if we can configure // a cell with CellData protocol ConfigureAbleWithCellData { func configure(_ data: CellData) } class MyCustomTableViewCell : UITableViewCell, ConfigureAbleWithCellData { @IBOutlet weak var title:UILabel! = nil func configure(_ data: CellData) { self.title.text = data.title } } // This actually holds the data for one cell struct CellData { var title:String = "" var reusableId:String = "" } class CosmoConverterUnitTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { // Storage var data = Array<Array<CellData>>() func loadData() { var section1:[CellData] = [] var section2:[CellData] = [] section1.append(CellData(title:"Foo", reusableId:"cellType1")) section2.append(CellData(title:"Bar", reusableId:"cellType2")) data.append(section1) data.append(section2) } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return data[section].count } public func numberOfSections(in tableView: UITableView) -> Int { return data.count } func tableView( _ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard indexPath.row < data[indexPath.section].count else { fatalError("this can't be") } let cellData = data[indexPath.section][indexPath.row] if let cell = tableView.tryDequeueReusableCell( withIdentifier: cellData.reusableId, for: indexPath) { if let configurableCell = cell as? ConfigureAbleWithCellData { configurableCell.configure(cellData) } else { // cell is not of type ConfigureAbleWithCellData // so we cant configure it. } return cell } // id does not exist return UITableViewCell.empty() } }
简而言之:
dequeueReusableCell(withIdentifier, for)
仅适用于原型单元格。 如果您在原型单元不在时尝试使用它,则会导致应用程序崩溃。
Hollemans M. 2016,第2章核对清单, IOS学徒 (第5版)。 pp:156。