2010-02-23 2 views
24

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

/Jimmy

+0

Обычно метод reloadData обновляет представление tableview. Не могли бы вы поместить образец вашего кода TableViewController? –

ответ

53

Вы сказали, что вы заселение содержание асинхронно но вы вызываете 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()); 
+7

Спасибо, что решил это =) Решение для monotouch: InvokeOnMainThread (() => this.TableView.ReloadData()); –

+0

@yonel У меня такая же проблема, как у JimmyEngtröm, и я действительно надеялся, что вы это сделаете, но, увы, у меня все еще есть эта проблема. Я не могу найти способ обновить UITableView после обновления базовых массивов данных, которые он использует. –

+0

@ MasonG.Zhwiti: установите точку останова в вашем методе numberOfRowsInSections в вашем источнике данных таблицы и проверьте, не идет ли он в нее после reloadData. Затем проверьте количество строк, которые вы здесь вернете, если это не 0, то он вызовет cellForRowAtIndex. – yonel

2

Я предполагаю, что это не был перезагружен.

Когда вы крутите клетки из экрана, а затем ...

tableView: cellForRowAtIndexPath:

... будет называться. Поэтому он будет перезагружен.

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

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

[self.view reloadData];

или

[self.tableView reloadData];

4

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

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

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

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

2

У меня была аналогичная проблема сегодня (раскадровка в iOS 7.0). Я использовал таблицу View внутри UIViewController. При просмотре представления все работало нормально; всех делегатов вызвали.Однако ; Когда базовый dataSource (в моем случае, Array) был изменен; строки видимой таблицы не обновлялись. Они были обновлены; только когда я прокручивал представление таблицы.

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

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

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

0

После некоторого наивного копирования в решении 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:, так как он выполняет ту же цель, но вы также должны понимать, что происходит в большой картине. Кроме того, если вы делаете больше работы с пользовательским интерфейсом, а не просто перезагружаете таблицу, тогда весь этот код должен также поступать в основную очередь.

Ссылка: A concise example Использование GCD и управление фоном по сравнению с основной нитью.

Смежные вопросы