Hatena::Groupiphone-dev

iPhoneアプリ開発まっしぐら★ このページをアンテナに追加 RSSフィード

引っ越し後の日記はコチラです

tokoromのその他の日記

2009-06-04

テーブルのセルの削除や追加にbeginUpdates/endUpdatesは必要か(2)

11:51 | はてなブックマーク - テーブルのセルの削除や追加にbeginUpdates/endUpdatesは必要か(2) - iPhoneアプリ開発まっしぐら★

前のエントリの続きです。

結論はというと、Appleのドキュメントに書いてあるとおりでした。

テーブルの削除/追加はbeginUpdates/endUpdatesブロックの中に記載しないと、行やセクションのインデックスが不正になりますよ。

beginUpdates/endUpdatesブロック内においては、テーブルのセルを削除しても削除前のインデックスが保持されます。例えば、

index0: Item 1

index1: Item 2

index2: Item 3

という3行のセルがあるテーブルに対して

NSIndexPath* path1 = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:path1] withRowAnimation:UITableViewRowAnimationTop];

と index0 の行を削除すると…

index0: Item 2

index1: Item 3

と、もともと2行め(index1)だったセルが1行め(index0)に繰り上がります。

慣れたプログラマからすれば当然と言えば当然の話ですが、beginUpdates/endUpdatesを使うと、より直感的に分かりやすいよう、そのブロック内にいるかぎりは

index1: Item 2

index2: Item 3

というように

元のインデックスが保持されたままになります。


上記をソースコードに落とすと、(DataSourceをitems_とする)

[self.tableView beginUpdates];

NSIndexPath* path1 = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:path1] withRowAnimation:UITableViewRowAnimationTop];
NSIndexPath* path2 = [NSIndexPath indexPathForRow:1 inSection:0];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:path2] withRowAnimation:UITableViewRowAnimationTop];
NSIndexPath* path3 = [NSIndexPath indexPathForRow:2 inSection:0];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:path3] withRowAnimation:UITableViewRowAnimationTop];
[items_ removeAllObjects];

[self.tableView endUpdates];

というコードは正常に動作し、3行のセルが全て削除されます。

ただし、上記コードからbeginUpdates/endUpdatesを外すと、プログラムは落ちます。

なぜなら、3回めの削除

NSIndexPath* path3 = [NSIndexPath indexPathForRow:2 inSection:0];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:path3] withRowAnimation:UITableViewRowAnimationTop];

で index:2 を指定していますが、この時点で index:2 のセルは存在しないからです。


ちなみにbeginUpdates/endUpdatesを使わない場合には以下のコードになります。

[items_ removeObjectAtIndex:0];
NSIndexPath* path1 = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:path1] withRowAnimation:UITableViewRowAnimationTop];
[items_ removeObjectAtIndex:0];
NSIndexPath* path2 = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:path2] withRowAnimation:UITableViewRowAnimationTop];
[items_ removeObjectAtIndex:0];
NSIndexPath* path3 = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:path3] withRowAnimation:UITableViewRowAnimationTop];

index:0 のセルを3回削除すれば、結果として全てのセルが削除されることになります。


【まとめ】

・beginUpdates/endUpdatesは必須ではない。

・beginUpdates/endUpdatesで囲っておけばより直感的にテーブル操作を行える。

AzamatAzamat2012/08/09 00:24That's a sbutle way of thinking about it.

zflhpcaclbzflhpcaclb2012/08/09 16:10McVtVi <a href="http://iujobmchnisp.com/">iujobmchnisp</a>

lncjuflnlncjufln2012/08/10 04:01pESIA6 <a href="http://rclahgawisti.com/">rclahgawisti</a>