Перерисовать UITableView после обновления данных async
У меня есть UITableview, в котором я загружаю данные async, поэтому представление таблицы может отображаться без данных.
Я устал от метода ReloadData, но tableview остается пустым, пока я не прокручу табличное представление, внезапно появятся данные.
То же самое происходит, когда я загружаю tableview в виде подробного просмотра и переключения между элементами, сначала отображаются данные предыдущих элементов, и как только я просматриваю в представлении таблицы, он показывает правильные данные.
Я предполагаю, что метод ReloadData работает очень хорошо, но мне нужно каким-то образом перерисовать табличное представление, какие-либо предложения по его решению?
/Джимми
Ответы
Ответ 1
Вы сказали, что вы заполняете контент асинхронно, но вы вызывали reloadData в контексте основного потока? (а не через поток, который заполняет контент)
Objective-C
[yourUITableView performSelectorOnMainThread:@selector(reloadData)
withObject:nil
waitUntilDone:NO];
Swift
dispatch_async(dispatch_get_main_queue(), { self.tableView.reloadData() })
MonoTouch
InvokeOnMainThread(() => this.TableView.ReloadData());
Ответ 2
Ответ на Yonels прекрасен, когда ваше представление в настоящее время отображается пользователю (например: Пользователь нажимает кнопку перезагрузки, которая заполняет ваш UITableView
.)
Однако, если ваши данные загружаются асинхронно, а ваш UITableView
не отображается во время обновления (например: вы добавляете данные в ваш UITableView
в другом представлении, а UITableView
отображается позже пользователем), просто переопределите UITableViewController
viewWillAppear
.
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.tableView reloadData];
}
Положительный эффект заключается в том, что ваш UITableView
только перезагружает его данные один раз, когда пользователь действительно хочет его видеть, а не при добавлении новых элементов.
Ответ 3
Я предполагаю, что он не перезагрузился.
Когда вы прокручиваете ячейки вне экрана, тогда...
tableView: cellForRowAtIndexPath:
... будет вызываться. Поэтому он будет перезагружен.
Я думаю, что переменная UITableView не проверяется.
Если вы используете UITableView в качестве основного вида, вы можете попробовать это.
[self.view reloadData];
или
[self.tableView reloadData];
Ответ 4
У меня была аналогичная проблема сегодня (Storyboard в iOS 7.0).
Я использовал table View внутри UIViewController. Когда представление было загружено, все работало нормально; все делегаты вызывались. Однако; Когда базовый dataSource (в моем случае, Array) был изменен; строки видимой таблицы не обновлялись. Они были обновлены; только когда я прокручивал представление таблицы.
Пробовал все; вызов reloadData в основном потоке; вызов reload в ViewWillAppear; ничего не работало.
Проблема, которую я нашел; было то, что я не установил связь в раскадровке; для представления таблицы со ссылкой Outlet.The dataSource и делегат были установлены, хотя.
Я не думал, что это может быть проблемой; так как все работало нормально с первого раза.
Надеюсь, что это поможет кому-то. У меня было какое-то ужасное время, чтобы это выяснить.
Ответ 5
После некоторого наивного копирования в решении yonel и называя его хорошим, я понял, что вызов performSelectorOnMainThread:withObject:waitUntilDone:
исправил симптом, но не проблему. Большая проблема заключается в том, что вы создаете обновления пользовательского интерфейса, все еще находясь в контексте асинхронного или фонового потока.
Вот как выглядел мой код:
dispatch_queue_t queue = dispatch_queue_create("com.kyleclegg.myqueue", NULL);
dispatch_async(queue, ^{
// Make API call
// Retrieve data, parse JSON, update local properties
// Make a call to reload table data
});
Когда это должно выглядеть так:
dispatch_queue_t queue = dispatch_queue_create("com.kyleclegg.myqueue", NULL);
dispatch_async(queue, ^{
// Make API call
// Retrieve data, parse JSON, update local properties
dispatch_async(dispatch_get_main_queue(), ^{
// Now make the call to reload data and make any other UI updates
[self.tableView reloadData]
});
});
Если вам нужно сделать только, это вызвать [self.tableView reloadData]
, возможно, хорошо использовать performSelectorOnMainThread:withObject:waitUntilDone:
, поскольку он выполняет ту же цель, но вы также должны понимать, что происходит на большой картинке. Кроме того, если вы выполняете больше работы с пользовательским интерфейсом, а не просто перезагружаете таблицу, то весь этот код также должен находиться в главной очереди.
Ссылка: Краткий пример использования GCD и управления фоном и основным потоком.
Ответ 6
Свифт 4:
DispatchQueue.main.async { self.tableView.reloadData() }