1. ホーム
  2. オブジェクティブC

[解決済み] [Solved] UITableViewがReloadDataを完了したことを伝えるには?

2022-04-12 05:12:37

質問

UITableViewのパフォーマンスが終了した後、一番下までスクロールさせようとしています。 [self.tableView reloadData]

私はもともと

 [self.tableView reloadData]
 NSIndexPath* indexPath = [NSIndexPath indexPathForRow: ([self.tableView numberOfRowsInSection:([self.tableView numberOfSections]-1)]-1) inSection: ([self.tableView numberOfSections]-1)];

[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];

しかし、reloadDataは非同期であることを読み、スクロールが起こらないのは self.tableView , [self.tableView numberOfSections][self.tableView numberOfRowsinSection はすべて0です。

ありがとうございます。

何が変かって、私が使っているのは

[self.tableView reloadData];
NSLog(@"Number of Sections %d", [self.tableView numberOfSections]);
NSLog(@"Number of Rows %d", [self.tableView numberOfRowsInSection:([self.tableView numberOfSections]-1)]-1);

コンソールでは、Sections = 1, Row = -1 が返されます。

全く同じNSLogを cellForRowAtIndexPath Sections = 1 と Row = 8; が表示されます(8が正しい)。

どのように解決するのですか?

リロードは次のレイアウトパスの間に行われます。これは通常、実行ループに制御を戻したとき(たとえば、ボタンアクションなどが戻った後)に起こります。

したがって、テーブル・ビューが再読み込みされた後に何かを実行する1つの方法は、単にテーブル・ビューが直ちにレイアウトを実行するように強制することです。

[self.tableView reloadData];
[self.tableView layoutIfNeeded];
 NSIndexPath* indexPath = [NSIndexPath indexPathForRow: ([self.tableView numberOfRowsInSection:([self.tableView numberOfSections]-1)]-1) inSection: ([self.tableView numberOfSections]-1)];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];

もう1つの方法は、アフターレイアウトのコードを後で実行するように dispatch_async :

[self.tableView reloadData];

dispatch_async(dispatch_get_main_queue(), ^{
     NSIndexPath* indexPath = [NSIndexPath indexPathForRow: ([self.tableView numberOfRowsInSection:([self.tableView numberOfSections]-1)]-1) inSection:([self.tableView numberOfSections]-1)];

    [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
});

アップデイト

さらに調べてみると、テーブルビューから tableView:numberOfSections:tableView:numberOfRowsInSection: から戻る前に、そのデータソースに reloadData . デリゲートが tableView:heightForRowAtIndexPath: から戻る前に、テーブルビューもそれを(各行に対して)送信します。 reloadData .

しかし、テーブルビューは tableView:cellForRowAtIndexPath: または tableView:headerViewForSection レイアウトフェーズまでは、デフォルトではランループに制御を戻したときに発生します。

また、小さなテストプログラムでは、ご質問のコードはテーブルビューの一番下まできちんとスクロールすることがわかりました。 なし を送信するような)特別なことは何もしていません。 layoutIfNeeded を使用したり dispatch_async ).