![](/img/trans.png)
[英]dequeueReusableCellWithIdentifier:forIndexPath: VS dequeueReusableCellWithIdentifier:
[英]When to use dequeueReusableCellWithIdentifier vs dequeueReusableCellWithIdentifier : forIndexPath
dequeueReusableCellWithIdentifier 有兩個重載,我正在嘗試確定何時應該使用一個還是另一個?
關於 forIndexPath 函數的蘋果文檔指出, “此方法使用索引路徑根據表格視圖中單元格的位置執行附加配置。”
我不知道如何解釋?
最重要的區別是,如果沒有為標識符注冊類或nib,則forIndexPath:
version會斷言(崩潰)。 在這種情況下,較舊的(非forIndexPath:
版本返回nil
。
您通過將registerClass:forCellReuseIdentifier:
發送到表視圖來registerClass:forCellReuseIdentifier:
標識符的類。 通過將registerNib:forCellReuseIdentifier:
發送到表視圖來registerNib:forCellReuseIdentifier:
標識符的nib。
如果您在故事板中創建表視圖和單元格原型,則storyboard加載程序負責注冊您在故事板中定義的單元格原型。
第200節 - 來自WWDC 2012的Cocoa Touch的新功能討論了(然后是新的) forIndexPath:
版本從forIndexPath:
左右開始。 它說“你將永遠得到一個初始化的單元格”(沒有提到如果你沒有注冊一個類或nib就會崩潰)。
該視頻還說“它將是該索引路徑的正確大小”。 據推測,這意味着它將在返回之前設置單元格的大小,方法是查看表格視圖自身的寬度並調用委托的tableView:heightForRowAtIndexPath:
方法(如果已定義)。 這就是它需要索引路徑的原因。
dequeueReusableCellWithIdentifier:forIndexPath:
將始終返回一個單元格。 它要么重新使用現有單元格,要么創建一個新單元格,如果沒有單元格則返回。
然而,傳統的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 :
我從來沒有理解為什么Apple創建了更新的方法,dequeueReusableCellWithIdentifier:forIndexPath:。 他們關於它們的文件不完整,有些誤導。 我能夠在兩種方法之間區分的唯一區別是,如果找不到傳入標識符的單元格,那么舊方法可以返回nil,而新方法崩潰,如果它不能返回一個細胞。 如果已正確設置標識符,則保證兩種方法都返回單元格,並在故事板中創建單元格。 如果您注冊類或xib,並且使用代碼或xib文件創建單元格,這兩種方法也可以保證返回單元格。
簡而言之:
dequeueReusableCell(withIdentifier, for)
僅適用於原型單元格。 如果您在原型單元格缺失時嘗試使用它,則會使應用程序崩潰。
Hollemans M. 2016,第2章清單, IOS學徒 (第5版)。 pp:156。
主要區別是你不能為同一個 indexPath 注冊兩個單元格,而只能使用你可以做到的重用標識符,如果單元格沒有針對該表視圖注冊,兩者都可以返回 nil
如果您使用動態生成的內容,我建議使用兩者。 否則您的應用可能會意外崩潰。 您可以實現自己的函數來檢索可選的可重用單元格。 如果它nil
,則應返回一個不可見的空單元格:
斯威夫特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()
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.