こんにちは。開発担当のICTFです。
データの表示用にUITableViewを使用していました。
その画面の一機能として不要な項目を削除するという機能を盛り込んだのですが、単純な機能ながらそこで1つ詰まってしまった箇所がありましたので、注意事項として記録しておきます。
今回はUITableViewをUIViewの上に貼付けるのではなく、UITableViewControllerを用いました。
IBで画面設計を行なったのですが、継承するクラスをUITableViewControllerに設定すると最初から必要なプロトコルをすべて乗せた状態のコードが書かれている状態なので凄く助かりますね。
前提として、
・NSMutableArrayにデータソースを読み込む。
・cellForRowAtIndexPathでデータソースのインデクス順にセルを追加する。
この状態からセルの削除処理を実装するものとします。
まず画面上に「Edit」ボタンを配置し、ボタンがタップされたタイミングでUITableViewの編集モードをONにします。
[self.tableView setEditing:YES animated:YES];
setEditingにYESを設定すると、UITableViewは編集モードに入ります。
こんな感じの画面ですね。
セル左側の赤い丸をタップすると、セル右側に「削除」ボタンが出現します。
「削除」ボタンをタップする事で、実際の削除処理が走ります。
セルは自動で削除される訳ではなく、削除ボタンタップ時の処理を自分で記述します。
削除ボタンがタップされると、次のメソッドがコールバックされます。
// 編集モード時のコールバック
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// 削除処理
// 該当するデータを削除する
[self deleteDataSource:indexPath.row];
// テーブルから該当セルを削除する
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// 挿入処理
}
}
すごく単純なソースなのですが、この処理で躓いてしまいました。
実装時、UITableViewからセルが削除される事だけをまず確認しようとして、[self deleteDataSource:indexPath.row]の中の処理をからっぽ、つまりデータソースから該当データの削除を行なわずにいました。
この状態で実行してみると、[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]を実行するタイミングでアプリがSIGBARTエラーを出力し、落ちてしまうのです。
deleteRowsAtIndexPathsのソースが公開されている訳ではないのでコードを追う事もできず苦労してしまいましたが、試しにデータソースから該当データを削除してから実行してみるとすんなりと正常動作を確認できました。
どうやら最初に紐づけたデータソースの数とセルを削除する際の数は必ず一致していなければならないようです。
私は基本的に最小機能を実装したら確認し、次の機能を盛り込みまた確認する・・・という手順を取る事が多いのですが、今回はこの手法が足を引っ張る結果となってしまいました。
どこまでを最小機能の単位とするかというのはなかなか難しい問題ですね。
それぞれのクラス(ブラックボックスであるなら尚更)の特性を財産として溜め込んで行くしか無さそうです。
コメントする