web-dev-qa-db-ja.com

reloadRowsAtIndexPathsを呼び出すと、UITableViewがセクションの先頭に戻る

ユーザーがいずれかの行のボタンをタップすると、その行の基になるモデルが更新され、指定された行のreloadRowsAtIndexPathsが呼び出されます(つまり、単一行の再読み込み)。

- (IBAction)handleCompleteTouchEvent:(UIButton *)sender {
    NSIndexPath *indexPath = [self.tableView indexPathForView:sender];
    id item = [self dataForIndexPath:indexPath];

    if ([item respondsToSelector:@selector(completed)]) {
        // toogle completed value
        BOOL completed = ![[item valueForKey:@"completed"] boolValue];
        [item setValue:[NSNumber numberWithBool:completed] forKey:@"completed"];

        [self.tableView beginUpdates];
        [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
        [self.tableView endUpdates];
    }
}

問題は、この呼び出しを行った後、テーブルビューがセクションの上部に跳ね返ることです。これが発生するのを防ぎ、スクロール位置をそのままにするにはどうすればよいですか?

38
xsee

あはは!私は問題を発見し、将来この問題に遭遇する貧しい魂に対する私自身の質問に答えます。

すべてのセルの高さが可変であるため、UITableViewDelegateで新しいiOS7メソッドを使用していたため、レンダリング時間が短縮されるのではないかと考えていました(本当に必要だったわけではありません)。

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath;

とにかく、このメソッドを実装すると、次の呼び出し時にテーブルがセクションの先頭に跳ね返るという悪影響があります。

[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];

バウンス問題を解決するために、私は見積もられたHeightForRowAtIndexPathメソッドのオーバーライドを削除しただけで、すべてが正常に機能します。やっと幸せ。

48
xsee

これは私にとってはトリックでした。

UIView.setAnimationsEnabled(false)
tableView.reloadRows(at: [...], with: .none)
UIView.setAnimationsEnabled(true)
4

セルの内容を直接変更することで、実行しようとしていることを実行できるはずです。たとえば、ベースUITableViewCellクラスを使用していて、モデルのデータがNSStringであり、テーブルビューのセルに表示されている場合、次のことができます(データを変更した後モデル)reloadRowsAtIndexPathsを呼び出す代わりに:

UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UILabel *label = [cell textLabel];
label.text = @"New Value";

UITableViewCellのカスタムサブクラスを使用している場合、セルのビューへのアクセスはcontentViewプロパティを介して行う必要があることを除いて、ほぼ同じです。

3
strwils

Swift 4.2

これは、アニメーションを削除したい場所であればどこでも機能します。テーブル、テーブルセクション、または任意の行の再読み込み中

 UIView.performWithoutAnimation({
                cell.configureSelection(isSelected: true)
                tableView.reloadSections([1], with: .none)
                tableView.allowsSelection =  false

            })
2
Tanvir Singh

セルを独自のセクションに配置し、reloadセクションを呼び出すことができる場合があります。

[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationFade];

これにより、問題が部分的に修正されたようです。きれいな方法ではありませんが、あなたのために働くかもしれません。

1
Vlad

私の同様のケースでは、メソッドの実装を微調整する必要がありました

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
...
}

私の身長がリセットされていた場所。したがって、すべてのセルの高さをリセットするのではなく、reloadRowsAtIndexPaths呼び出しの影響を受けるセルのみを更新しました。

1
zeeawan

同じ問題がありました。データ/セルを更新した後、代わりにtableView.reloadData()を呼び出すだけで終了しましたが、先頭に戻りませんでした/データが適切に更新されました-FYI

0
devjme

Xseeの答えを基にするには-インターフェイスビルダーでEstimateを「自動」に設定しました。これを別の番号に変更すると、機能し始めました。 Row Height自動に。

0
Michael McKenna

セルの最小の高さがわかっている場合は、estimatedRowHeightを設定するときにその高さを指定する必要があります。以前にどこかで読んだように、私はそれを1に設定していましたが、0を超える値は目的を十分に満たしますが、それは原因です。

セルの最小高さである44に設定すると、すべて正常に動作しました。

動的な高さも問題なく機能し、この修正に関する問題はありません。

0
nr5