5

私の質問は、UITableView の「見えない」行を削除することです。非表示とは、画面に表示されない行を意味します。たとえば、UITableView メソッドを呼び出すことによって返されないすべての行- (NSArray *)visibleCells

「拡張可能な」UITableViewを開発しているため、これを求めています。ちょっと木っぽい。次のようなテーブルを作成できます。

  • メニュー 1
    1. メニュー 1.1
    2. メニュー 1.2
  • メニュー 2
    1. メニュー 2.1
    2. メニュー 2.2

"Menu 1"セル"Menu 1.1"をクリックする"Menu 1.2"と、表示または非表示になります。アニメーションでセルを挿入または削除するだけでこれを行います。

問題は、長いメニューがあり、ユーザーがスクロールする場合、たとえば「メニュー 1」の半分の行が非表示 (表示されない、画面に表示されない、下にスクロールした場合にのみ表示される) 場合、ユーザーが「メニュー 1」を削減したいのですが、表示されていない行を削除しようとしているため、アプリケーションがクラッシュします。

実際のエラー メッセージは次のとおりです。

*キャッチされない例外 'NSInternalInconsistencyException' が原因でアプリを終了します。理由: '無効な更新: セクション 0 の行数が無効です。更新後の既存のセクションに含まれる行数 (11) は、更新前のそのセクション (15)、そのセクションから挿入または削除された行数 (0 挿入、0 削除) のプラスまたはマイナス、およびそのセクションに移動またはセクションから移動された行の数 (0 移動、0引っ越した)。'

すべての行を表示してまったく同じ操作を行うと、アプリとメニューに問題はなく、正しく動作します。

4

3 に答える 3

0

同様の問題がありましたが、ここに私の解決策があります。基本的に、解決策には、セルの高さを変更して「非表示」にすることが含まれます。

セクション ヘッダーをカスタム UIControl に変更して、他のセルのように見えるようにし、フォロー メソッドを実装して、選択したセクションの外側の行を「非表示」にしました。

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == _selectedSection) {
        // If it is the selected section then the cells are "open"
        return 60.0;
    } else {
        // If is not the selected section then "close" the cells
        return 0.0;
    }
}

カスタム ヘッダーには、次のコードを使用しました。

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    CGFloat height = [self tableView:tableView heightForHeaderInSection:section];

    // Here you can use whatever you want
    CGFloat width = 640.0;

    UIControl *view = [[UIControl alloc] initWithFrame:CGRectMake(0.0, 0.0, width, height)];

    view.tag = section;

    // This code is used by my custom UIControl
    //
    // to change the style for each state
    // view.sectionSelected = (section == _selectedSection);
    //
    // and to change the title
    // view.title = [self tableView:tableView titleForHeaderInSection:section];

    // This event is used to "close" or "open" the sections
    [view addTarget:self action:@selector(didSelectSectionHeader:) forControlEvents:UIControlEventTouchUpInside];

    return view;
}

より魅力的にするために、次のメソッドにアニメーションを追加しました。

- (void)didSelectSectionHeader:(id)sender
{
    if ([sender isKindOfClass:[UIControl class]]) {
        // Save the old section index
        int oldSelection = _selectedSection;

        // Get the new section index
        int tag = ((UIControl *)sender).tag;

        // Get sections quantity
        int numSections = [self numberOfSectionsInTableView:_tableView];

        // Check if the user is closing the selected section
        if (tag == _selectedSection) {
            _selectedSection = -1;
        } else {
            _selectedSection = tag;
        }

        // Begin animations
        [_tableView beginUpdates];

        // Open the new selected section
        if (_selectedSection >= 0 && _selectedSection < numSections) {
            [_tableView reloadSections:[NSIndexSet indexSetWithIndex:_selectedSection] withRowAnimation:UITableViewRowAnimationAutomatic];
        }

        // Close the old selected section
        if (oldSelection >= 0 && oldSelection < numSections) {
            [_tableView reloadSections:[NSIndexSet indexSetWithIndex:oldSelection] withRowAnimation:UITableViewRowAnimationAutomatic];
        }

        [_tableView endUpdates];
    }
}
于 2013-06-04T15:55:03.257 に答える
0

皆様、ご回答ありがとうございます。私がしたことは、 「indexPathsForVisibleRows」を使用して画面に表示されていない行のindexPathを取得し、単にモデルを更新して「reloadData」を呼び出してテーブルを更新したことです。これは私が期待していた理想的な解決策ではありませんが、うまくいきます。

「-deleteRowsAtIndexPaths」が画面上ではなく実際にテーブルに存在する行に対して機能しない理由はまだわかりません。

于 2013-06-04T15:26:04.203 に答える