簡體   English   中英

何時使用 dequeueReusableCellWithIdentifier 與 dequeueReusableCellWithIdentifier : forIndexPath

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM