Подтвердить что ты не робот

Перерисовать UITableView после обновления данных async

У меня есть UITableview, в котором я загружаю данные async, поэтому представление таблицы может отображаться без данных.
Я устал от метода ReloadData, но tableview остается пустым, пока я не прокручу табличное представление, внезапно появятся данные.
То же самое происходит, когда я загружаю tableview в виде подробного просмотра и переключения между элементами, сначала отображаются данные предыдущих элементов, и как только я просматриваю в представлении таблицы, он показывает правильные данные.
Я предполагаю, что метод ReloadData работает очень хорошо, но мне нужно каким-то образом перерисовать табличное представление, какие-либо предложения по его решению?

/Джимми

4b9b3361

Ответ 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() }