2013/12/9更新。iOS 7に対応しました。

前回の続き。今回はセルの削除と移動を行うサンプルの説明です。

サンプルコード: https://github.com/stack3/UITableViewSamples

サンプルを起動して、Editingを選択してください。以下の様な画面が表示されます。

01

セルの上で右から左へスワイプするとDeleteボタンが表示されます。

02

右上のEditボタンを押すと以下の様になります。

03

左端の赤いボタンを押すと横線が縦線に変わり、Deleteボタンが表示されます。ちなみに端末の言語環境が日本語だと削除という表示になります。

04

Deleteボタンを押すと、アニメーションしてスッと項目が削除されます。

05

右上のCancelボタンを押すと元に戻ります。

06

もう一度、Editボタン押しましょう。今度はセルの右端を指で押しながら移動すると、それにしたがってセルも移動することを確認しましょう。

07

09

08

削除ボタンの表示や移動操作まわりは、自分でプログラミングする必要はなくUITableViewがやってくれます。自分でやることは、UITableViewDelegateのメソッドを適切に実装するだけです。

セルの表示

セルの表示のためのUITableViewDataSourceの実装、および行データ(_rows)の初期化は、チュートリアル その1とほとんど同じなので割愛します。

Editボタンの表示とEditモードへ切り替え

viewDidLoadでNavigationBarの右側にEditボタンを表示します。

self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Edit"
                                                                          style:UIBarButtonItemStyleBordered
                                                                         target:self
                                                                         action:@selector(didTapEditButton)];

このボタンが押された時に、UITableViewをEditモードへ切り替えます。すでにEditモードの時は元に戻します。

- (void)didTapEditButton
{
    [_tableView setEditing:!_tableView.editing animated:YES];
    if (_tableView.editing) {
        self.navigationItem.rightBarButtonItem.title = @"Cancel";
    } else {
        self.navigationItem.rightBarButtonItem.title = @"Edit";
    }
}

ちなみにEditモード時はボタンのタイトルがCancelになるようにしています。

セルの削除

セルの削除は以下のUITableViewDelegateメソッドを実装します。

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        [_rows removeObjectAtIndex:indexPath.row];
        [_tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    }
}

このメソッドは削除ボタンが押されたセルのインデックス(indexPath引数)を受け取ります。

  • 行データ(セルの表示の元となるデータ)を削除
  • 行データとセル表示を同期させるために、UITableView#deleteRowsAtIndexPaths:withRowAnimationを使って、セルを削除

単純にUITableView#reloadDataを呼んでも削除したセルは消えますが、アニメーションはしません。アニメーションさせたほうが見栄えが良いと思います。withRowAnimation引数は、UITableViewRowAnimationAutomaticを指定していますが、他にも

  • UITableViewRowAnimationRight: 右側へスライドして消える
  • UITableViewRowAnimationMiddle: 上下から真ん中に向かって覆い隠すように消える

といった指定ができます。この辺はお好みで良いのではないでしょうか。

セルの移動

まず移動を許可するために以下のメソッドでYESを返すようにします。ここでYESを返すことで、編集時に右側に三本線の移動ボタンが表示されるようになります。

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

先述したとおりセルの移動操作の処理はUITableViewが自動で行います。我々は移動が完了した時に呼ばれる以下のUITableViewDelegateメソッドを実装します。

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
    if (destinationIndexPath.row < _rows.count) {
        // sourceIndexPath(移動元のインデックス)から、行データを得る
        NSString *title = [_rows objectAtIndex:sourceIndexPath.row];
        // いったん移動元の行データを削除する
        [_rows removeObjectAtIndex:sourceIndexPath.row];
        // destinationIndexPath(移動先のインデックス)へ、行データを挿入する
        [_rows insertObject:title atIndex:destinationIndexPath.row];
    }
}

これで表示上のセル移動と行データが同期するようになります。

以上、セルの削除と移動でした。

その5へ続く。