2012年8月13日月曜日

UITableView でセクションが複数ある場合の複数選択&削除を実装してみた


すごい面倒くさかった
セクションが1つだけの場合は簡単なのですが、セクションが複数存在するようになった途端に面倒くさくなります。

サンプルを書いてみました。
UITableViewの見た目はデフォルトです。
各セクションで行の数が0になると、そのセクションも削除するようにしました。

けっこうきれいに、滑らかなUIで実現できました。

このエントリの目次
  1. サンプルコード
  2. 複数選択の方法
  3. 選択したセルの取得
  4. データの削除
  5. UITableViewの表示からも削除
  6. 空になったセクションの削除
  7. さいごに

1.サンプルコード
githubにあげました。
2.複数選択の方法
self.tableView.allowsMultipleSelectionDuringEditing = YES;
とすると、編集モードのときに複数選択ができるようになります。

3.選択したセルの取得
[self.tableView indexPathsForSelectedRows];
とすると、indexPath(sectionとrowがセットになったオブジェクト)のNSArrayが取得できます。

ここで注意点ですが、sectionやrowの順ではなく、選択した順に配列にindexPathが格納されています。

4.データの削除
ここからは、データの構成によって処理方法は変わると思います。
本サンプルではループをまわして、セクション毎に行を一括削除しています。
gIthubのこのクラスの123行目からにあたります。

以下長いですが、サンプルの抜粋します。
    //「選択したセルたちのindexPath」が配列のかたちで取得できる
    NSArray *indexPaths = [self.tableView indexPathsForSelectedRows];
    
    //選択されたセルが含まれるセクション番号一覧を取得(値の重複はさせない)
    NSMutableSet *selectedUniqueSections = [NSMutableSet set];
    for (NSIndexPath *tempIndexPath in indexPaths) {
        [selectedUniqueSections addObject:[NSNumber numberWithInteger:tempIndexPath.section]];
    }
    
    //各セクション番号と、それに紐づく行番号たちをdictionary形式で取得
    NSMutableDictionary *selectedSectionAndRows = [NSMutableDictionary dictionary];
    for (NSNumber *selectedSection in selectedUniqueSections) {
        NSMutableArray *selectedRows = [NSMutableArray array];
        
        for (NSIndexPath *indexPath in indexPaths) {
            if (indexPath.section == [selectedSection intValue]) {
                NSArray *tableDataRow = [[tableData objectAtIndex:indexPath.section] objectForKey:KEY_ROW];
                NSString *selectedRowValue = [tableDataRow objectAtIndex:indexPath.row];
                [selectedRows addObject:selectedRowValue];
            }
        }
        [selectedSectionAndRows setObject:selectedRows forKey:selectedSection];
    }
    
    //各セクション毎に、その中の行を一括で削除する
    for (NSNumber *section in selectedSectionAndRows) {
        NSInteger sectionInteger = [section intValue];
        NSArray *selectedRow = [selectedSectionAndRows objectForKey:section];
        [[[tableData objectAtIndex:sectionInteger] objectForKey:KEY_ROW] removeObjectsInArray:selectedRow];
    }

5.UITableViewの表示からも削除
以下サンプルの抜粋。
    //UITableViewの表示からも削除する
    [self.tableView beginUpdates];
    [self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
    [self.tableView endUpdates];

6.空になったセクションの削除
本サンプルではループをまわしてセクション毎に行数を数え、ゼロだったセクションを削除しています。

以下にサンプルの抜粋をします。
    //セクション中の行が0になった場合、削除する
    NSMutableIndexSet *zeroRowSections = [NSMutableIndexSet indexSet];
    for (NSInteger i = 0; i < [tableData count]; i++) {
        if ([[[tableData objectAtIndex:i] objectForKey:KEY_ROW] count] == 0) {
            [zeroRowSections addIndex:i];
        }
    }
    
    //行数がゼロのセクションがあれば、そこのデータを一括削除し、表示をリロードする
    if ([zeroRowSections count] > 0) {
        [tableData removeObjectsAtIndexes:zeroRowSections];
        [self.tableView reloadData];
    }
7.さいごに
かなり面倒くさかったんですが、きれいなUIを実現できました。

というか泥臭すぎる気がするんですが、データの持ち方がよくないような気がします。
複数セクションの場合、どのようにデータを持てば簡単に処理ができるのでしょうか…

参考になれば幸いです。
それでは。

0 件のコメント:

コメントを投稿


Related Posts Plugin for WordPress, Blogger...