回答:
最も重要な違いはforIndexPath:
、識別子のクラスまたはnibを登録しなかった場合、バージョンがアサート(クラッシュ)することです。その場合、古い(非forIndexPath:
)バージョンが返さnil
れます。
registerClass:forCellReuseIdentifier:
テーブルビューに送信して、識別子のクラスを登録します。registerNib:forCellReuseIdentifier:
テーブルビューに送信して、識別子のnibを登録します。
ストーリーボードにテーブルビューとセルプロトタイプを作成すると、ストーリーボードローダーが、ストーリーボードで定義したセルプロトタイプの登録を処理します。
セッション200-WWDC 2012のCocoa Touchの新機能では、8分forIndexPath:
30秒頃に始まる(当時の)バージョンについて説明しています。「常に初期化されたセルを取得する」(クラスまたはnibを登録しないとクラッシュすることは言うまでもありません)と書かれています。
ビデオはまた「それはその索引パスに適切なサイズになるだろう」と述べています。おそらくこれは、テーブルビュー自体の幅を確認し、デリゲートのtableView:heightForRowAtIndexPath:
メソッド(定義されている場合)を呼び出すことによって、セルを返す前にセルのサイズを設定することを意味します。 これが、インデックスパスが必要な理由です。
dequeueReusableCellWithIdentifier:forIndexPath:
う、常にセルを返します。既存のセルを再使用するか、新しいセルを作成してセルがない場合は戻ります。
一方、従来型dequeueReusableCellWithIdentifier:
は、存在する場合、つまり再利用可能なセルがある場合はセルを返し、それ以外の場合はnilを返します。したがって、nil
値をチェックするための条件も作成する必要があります。
はiOS 6 dequeueReusableCellWithIdentifier:
以降dequeueReusableCellWithIdentifier:forIndexPath
でのみ利用可能であるため、iOS 5以前のバージョンをサポートする場合は、質問に答える
リファレンス:https : //developer.apple.com/library/ios/documentation/uikit/reference/UITableView_Class/Reference/Reference.html#//apple_ref/occ/instm/UITableView/dequeueReusableCellWithIdentifier: forIndexPath:
[self.tableView registerNib:[UINib nibWithNibName:@"cell" bundle:nil] forCellReuseIdentifier:@"cell"];
なぜAppleが新しいメソッドdequeueReusableCellWithIdentifier:forIndexPath:を作成したのか理解したことがありません。それらに関するドキュメントは完全ではなく、誤解を招く可能性があります。2つのメソッドを区別できた唯一の違いは、古いメソッドは、渡された識別子を持つセルが見つからない場合はnilを返すことができ、新しいメソッドは返せない場合はクラッシュすることです。細胞。どちらの方法でも、識別子を正しく設定してセルをストーリーボードに作成すると、セルが返されることが保証されます。クラスまたはxibを登録し、コードまたはxibファイルでセルを作成すると、どちらのメソッドもセルを返すことが保証されます。
tableView.estimateHeight
と、セルのサイズも適切に決定されます。新しい方法のメリットはまだ得られません。
動的に生成されたコンテンツを使用している場合は、両方を使用することをお勧めします。そうしないと、アプリが予期せずクラッシュする可能性があります。独自の関数を実装して、オプションの再利用可能なセルを取得できます。そうであれば、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()
}
}