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

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

/Джимми


person Jimmy Engtröm    schedule 23.02.2010    source источник
comment
Обычно метод reloadData обновляет представление таблицы. Не могли бы вы поместить образец своего кода TableViewController?   -  person Yannick Loriot    schedule 24.02.2010


Ответы (6)


Вы сказали, что заполняете контент асинхронно, но вызывали ли вы reloadData в контексте основного потока? (а не через поток, заполняющий контент)

Цель-C

[yourUITableView performSelectorOnMainThread:@selector(reloadData)
                                  withObject:nil 
                               waitUntilDone:NO];

Swift

dispatch_async(dispatch_get_main_queue(), { self.tableView.reloadData() })

Одно касание

InvokeOnMainThread(() => this.TableView.ReloadData());
person yonel    schedule 24.02.2010
comment
Спасибо, что решил это =) решение для монотач: InvokeOnMainThread (() = ›this.TableView.ReloadData ()); - person Jimmy Engtröm; 24.02.2010
comment
@yonel У меня та же проблема, что и у JimmyEngtröm, и я очень надеялся, что то, что вы сказали, сработает, но, увы, у меня все еще есть эта проблема. Я не могу найти способ обновить UITableView после обновления базовых массивов данных, которые он использует. - person Mason G. Zhwiti; 11.10.2011
comment
@ MasonG.Zhwiti: установите точку останова в методе numberOfRowsInSections в источнике данных таблицы и проверьте, входит ли она в него после reloadData. Затем проверьте количество строк, которые вы возвращаете сюда, если это не 0, тогда он вызовет cellForRowAtIndex. - person yonel; 11.10.2011
comment
На мой взгляд, это обходной путь, когда реальная проблема заключается в том, что вам, вероятно, не следует делать какие-либо обновления пользовательского интерфейса, все еще находясь в фоновом потоке. Я добавил еще один ответ, который объясняет более подробно ниже. - person Kyle Clegg; 06.03.2014
comment
Чтобы сделать это быстро, используйте dispatch_async(dispatch_get_main_queue(), { self.tableView.reloadData() }) - person SimplGy; 24.05.2015

Ответ Yonels идеален, когда ваше представление в настоящее время видно пользователю (например, пользователь нажимает кнопку перезагрузки, которая заполняет ваш UITableView.)

Однако, если ваши данные загружаются асинхронно и ваш UITableView не отображается во время обновления (например: вы добавляете данные в свой UITableView в другом представлении, а UITableView отображается позже при вводе пользователем), просто переопределите viewWillAppear метод UITableViewController.

- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.tableView reloadData];
}

Положительный эффект заключается в том, что ваш UITableView перезагружает данные только один раз, когда пользователь действительно хочет их увидеть, а не при добавлении новых элементов.

person Jay    schedule 07.01.2013

Сегодня у меня была аналогичная проблема (Раскадровка в iOS 7.0). Я использовал представление таблицы внутри UIViewController. Когда представление было загружено, все работало нормально; вызвали всех делегатов. Когда базовый источник данных (в моем случае, массив) был изменен; видимые строки таблицы не обновлялись, они обновлялись; только когда я прокручивал табличное представление.

Все перепробовал; вызов reloadData в основном потоке; вызов reload в ViewWillAppear; ничего не работало.

Проблема, которую я обнаружил; было то, что я не сделал связи в раскадровке; для табличного представления со ссылкой Outlet, хотя источник данных и делегат были установлены. Я не думал, что это могло быть проблемой; так как с первого раза все работало нормально.

Надеюсь, это кому-то поможет. У меня было ужасное время, чтобы узнать это.

person RUppal    schedule 08.02.2014

Полагаю, он не перезагружался.

Когда вы прокручиваете ячейки за пределы экрана, то…

tableView: cellForRowAtIndexPath:

… Будет называться. Так что он будет перезагружен.

Я предполагаю, что переменная UITableView не проверена.

Если вы используете UITableView в качестве основного представления, вы можете попробовать это.

[self.view reloadData];

or

[self.tableView reloadData];

person Joey    schedule 24.02.2010

Swift 4:

DispatchQueue.main.async { self.tableView.reloadData() }
person Nate Uni    schedule 20.01.2019

Несколько наивно скопировав решение 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 и управления фоновым потоком по сравнению с основным потоком.

person Kyle Clegg    schedule 05.03.2014