Appleが最初のiPhone用にUITableView
を開発したとき、スクロールするとパフォーマンスに問題がありました。その後、賢いエンジニアの1人が、この原因はオブジェクトの割り当てが原因であることを発見しました代金を払って、彼は細胞を再利用する方法を思いついた。
「オブジェクトの割り当てには、特にユーザーがテーブルビューをスクロールするときなど、割り当てを短期間に繰り返し行う必要がある場合、パフォーマンスコストがかかります。新しいセルを割り当てる代わりにセルを再利用すると、テーブルビューのパフォーマンスが大幅に向上します。」
ソース:iOSリファレンスライブラリ
使用するセルを再利用するには:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
さて、ここで実際に何が起こるのでしょうか。その識別子を持つセルがあり、そのセルを返す場合、TableViewを調べますか?ええ、そうですが、割り当ての代わりに参照を送信し、テーブルビューがあり、すべて同じ識別子を持つ4つのセルがすべて表示されているとしましょう。割り当てることなく、それ自体をどのようにして4つのインスタンスに乗算できますか?
カレンダータイプのコンポーネントを作成していて、すべてのセルが同じ構造を持っているのは、変更内のテキストのみなので、これを知りたいのです。したがって、割り当ての代わりに何らかの方法でセルを再利用できれば、より良いパフォーマンスが得られると思います。
私自身の理論では、4つのセルが割り当てられているとしています(単にそうしているからです)。セルが画面から消えると、TableView再利用キューに入れられます。新しいセルが必要な場合、同じ識別子のセルが利用可能かどうかをキューで調べ、そのセルでprepareForReuse
メソッドを呼び出して、キューから自分自身を削除します。
dequeueReusableCellWithIdentifier:
は、再利用可能としてマークされている場合にのみcell
を返します。これが、ほとんどすべてのcellForRowAtIndexPath:
メソッドで次のようなものが表示される理由です
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (nil == cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
// Do something to cell
return cell;
実際には、tableview
(さらに1つまたは2つ以上)の可視部分を満たすのに十分な行が割り当てられます。画面からcells scroll
がオフになると、table
から削除され、reuse
の準備ができているとマークされます。 「使用可能なセル」のキューが大きくなると、dequeued cell
を要求する行が、使用するcell
の取得を開始します。この時点で、割り当てる必要はありません。
deqeueueReusableCellsWithIdentifier:
のコードは次のようになります。
(私がページスクロールビューのビュー/ページで同様のことをしている自分のプロジェクトの1つから取られました)
- (UIView*) dequeueReusablePage
{
UIView* page = [reusablePages_ anyObject];
if (page != nil) {
[[page retain] autorelease];
[reusablePages_ removeObject: page];
}
return page;
}
そのため、再利用可能なオブジェクトを含む単純なNSMutableSet
が保持されます。
セルが画面からスクロールして見えなくなると、このセットに入れられます。
したがって、空のセットから始めて、実際に表示するデータが他にある場合にのみセットが大きくなり、画面に表示されます。
使用済みのセルは、画面上部からスクロールしてセットに入れられ、画面下部に表示されるセルに割り当てられます。
dequeueReusableCellWithIdentifier
の目的は、使用するメモリを少なくすることです。 tableViewで100個のセルを使用する場合、毎回100個のセルを作成する必要があります。アプリの機能が低下し、クラッシュが発生する可能性があります。そのため、dequeueReusableCellWithIdentifier
は、作成した特定の数のセルを初期化します。セルは、さらに処理するために再度使用します。
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *TableIdentifier = @"YourCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TableIdentifier];
}
ExternalClassTableViewCell *myCell = [[ExternalClassTableViewCell alloc]init];
myCell.MyCellText.text = [tableData objectAtIndex:indexPath.row];
myCell.MyCellImage.backgroundColor = [UIColor blueColor];
return cell;
}