需要[tableView reloadData]後需要立即獲取tableview的cell、高度,或者需要滾動tableview,那麼,直接在reloadData後執行代碼是會有問題的。
斷點調試感覺[tableview reloaddata]是個異步操作導致下面的代碼並不會再它執行完後才執行。
於是就想到了多線程,最簡單使用動畫來延遲執行
[UIView animateWithDuration:0.3 animations:^{ [self.collectionView reloadData]; } completion:^(BOOL finished) { [self.collectionView setContentOffset:offset animated:NO]; }];
解決是解決了,但是感覺有特別明顯的動畫效果還是去查了資料才知道是runloop的原因而不是異步問題
大神解說是因為[tableview reloaddata] 需要在當前方法在runloop中執行完後它再在runloop中執行,處理函數是在runloop中串行的排隊執行的。但是[tableview reloaddata]後面的代碼需要[tableview reloaddata]的計算結果,所以[tableview reloaddata]後面的代碼需要一個延遲執行。只有當前方法不再占用runloop,[tableview reloaddata]才可以在runloop中執行,而這時延遲執行的部分在runloop中早就排在了[tableview reloaddata]的前面執行完了。如果表中的數據非常大,在一個runloop周期沒執行完,這時,需要tableview視圖數據的操作就會出問題了。apple並沒有直接提供reloadData的api,想要程序延遲到reloadData結束再操作,可以用以下方法
方法1:layoutIfNeeded會強制重繪並等待完成
[self.tableView reloadData]; [self.tableView layoutIfNeeded]; //刷新完成
方法2:
reloadData會在主隊列執行,而dispatch_get_main_queue會等待機會,直到主隊列空閒才執行。
[self.collectionView reloadData]; dispatch_async(dispatch_get_main_queue(), ^{ // 刷新完成 [self.collectionView setContentOffset:offset animated:NO]; }); }