Quand utiliser dequeueReusableCellWithIdentifier vs dequeueReusableCellWithIdentifier: forIndexPath

Il y a deux surcharges pour dequeueReusableCellWithIdentifier et j'essaie de déterminer quand devrais-je utiliser l'un par rapport à l'autre?

Les docs apple concernant la fonction forIndexPath indiquent: "Cette méthode utilise le path d'index pour effectuer une configuration supplémentaire en fonction de la position de la cellule dans la vue tabulaire."

Je ne suis pas sûr de savoir comment interpréter cela?

La différence la plus importante est que forIndexPath: version forIndexPath: (crash) si vous n'avez pas enregistré de class ou de nib pour l'identifiant. L'ancienne version (non forIndexPath: renvoie nil dans ce cas.

Vous enregistrez une class pour un identifiant en envoyant registerClass:forCellReuseIdentifier: à la vue de la table. Vous enregistrez un nib pour un identifiant en envoyant registerNib:forCellReuseIdentifier: à la vue de la table.

Si vous créez votre vue de table et vos prototypes de cellule dans un storyboard, le chargeur de storyboard prend soin d'save les prototypes de cellules que vous avez définis dans le storyboard.

Session 200 – Quoi de neuf dans Cocoa Touch de la WWDC 2012 discute de la (pour l' forIndexPath: ) forIndexPath: version commençant vers 8m30s. Il dit que "vous aurez toujours une cellule initialisée" (sans mentionner qu'il va planter si vous n'avez pas enregistré une class ou une plume).

La video dit aussi que "ce sera la bonne taille pour ce path d'index". Cela signifie probablement qu'il va définir la taille de la cellule avant de la renvoyer, en regardant la largeur de la vue table et en appelant la tableView:heightForRowAtIndexPath: votre délégué (si elle est définie). C'est pourquoi il a besoin du path d'index.

dequeueReusableCellWithIdentifier:forIndexPath: returnne toujours une cellule. Il réutilise des cellules existantes ou en crée une nouvelle et returnne s'il n'y a pas de cellules.

Alors que le traditionnel dequeueReusableCellWithIdentifier: returnnera une cellule si elle existe, c'est-à-dire s'il y a une cellule qui peut être réutilisée, elle renvoie celle-là sinon elle renvoie nil. Donc, vous devrez écrire une condition pour vérifier la valeur nil .

Pour répondre à votre question, utilisez dequeueReusableCellWithIdentifier: lorsque vous voulez prendre en charge iOS 5 et les versions inférieures depuis dequeueReusableCellWithIdentifier:forIndexPath n'est disponible que sur iOS 6+

Référence: https://developer.apple.com/library/ios/documentation/uikit/reference/UITableView_Class/Reference/Reference.html#//apple_ref/occ/instm/UITableView/dequeueReusableCellWithIdentifier:forIndexPath :

Je n'ai jamais compris pourquoi Apple a créé la nouvelle méthode, dequeueReusableCellWithIdentifier: forIndexPath :. Leur documentation sur eux n'est pas complète et est quelque peu trompeuse. La seule différence que j'ai pu discerner entre les deux methods, c'est que cette ancienne méthode peut renvoyer zéro, si elle ne trouve pas de cellule avec l'identifiant transmis, tandis que la nouvelle méthode se bloque, si elle ne peut pas returnner une cellule. Les deux methods sont garanties de renvoyer une cellule, si vous avez correctement défini l'identificateur, et de faire la cellule dans un storyboard. Les deux methods sont également garanties pour returnner une cellule si vous enregistrez une class ou xib, et faites votre cellule dans le code ou un file xib.

Je reorderais d'utiliser les deux si vous utilisez du contenu généré dynamic. Sinon, votre application risque de tomber en panne de manière inattendue. Vous pouvez implémenter votre propre fonction pour récupérer une cellule réutilisable facultative. Si c'est nil vous devriez returnner une cellule vide qui n'est pas visible:

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: Ssortingng, for indexPath: IndexPath) -> UITableViewCell? { let cell = self.dequeueReusableCell(withIdentifier: identifier) if cell != nil { return self.dequeueReusableCell(withIdentifier: identifier, for: indexPath) } return nil } } 

Et l'extension pour returnner une cellule vide:

 // 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 } } 

Un exemple complet de comment l'utiliser:

 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:Ssortingng = "" var reusableId:Ssortingng = "" } 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() } } 

Pour faire court:

dequeueReusableCell(withIdentifier, for) ne fonctionne qu'avec des cellules prototypes. Si vous avez essayé de l'utiliser lorsque la cellule prototype est en panne, l'application tomberait en panne.

Hollemans M. 2016, chapitre 2 list de contrôle, IOS apprenti (5e édition). pp: 156.