UICollectionView не обновляется сразу при вызове reloadData, но случайно после 30-60 секунд
Как следует из названия, мой UICollectionView
не обновляет и не отображает ячейки сразу после вызова reloadData
. Вместо этого он, похоже, в конечном итоге обновляет мой просмотр коллекции через 30-60 секунд. Моя настройка такова:
UICollectionView
добавлен в контроллер просмотра в Storyboard с настройками delegate
и dataSource
для контроллера вида и стандартной настройки выхода
numberOfSectionsInRow
и cellForItemAtIndexPath
оба реализованы и ссылаются на прототипированную ячейку и imageView
внутри нее
Вот код, который идет в Twitter, получает временную шкалу, присваивает ее переменной, перезагружает табличное представление с помощью твитов, а затем просматривает твиты, чтобы найти фотографии и перезагружает представление коллекции этими элементами.
Даже если я прокомментирую код для отображения изображения, он все равно ничего не меняет.
SLRequest *timelineRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodGET URL:timelineURL parameters:timelineParams];
[timelineRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if(responseData) {
JSONDecoder *decoder = [[JSONDecoder alloc] init];
NSArray *timeline = [decoder objectWithData:responseData];
[self setTwitterTableData:timeline];
for(NSDictionary *tweet in [self twitterTableData]) {
if(![tweet valueForKeyPath:@"entities.media"]) { continue; }
for(NSDictionary *photo in [[tweet objectForKey:@"entities"] objectForKey:@"media"]) {
[[self photoStreamArray] addObject:[NSDictionary dictionaryWithObjectsAndKeys:
[photo objectForKey:@"media_url"], @"url",
[NSValue valueWithCGSize:CGSizeMake([[photo valueForKeyPath:@"sizes.large.w"] floatValue], [[photo valueForKeyPath:@"sizes.large.h"] floatValue])], @"size"
, nil]];
}
}
[[self photoStreamCollectionView] reloadData];
}
}];
Ответы
Ответ 1
Это классический симптом вызова методов UIKit из фонового потока. Если вы просмотрите документацию -[SLRequest performRequestWithHandler:]
, в ней говорится, что обработчик не гарантирует, какой поток будет запущен.
Настройте свой вызов на reloadData
в блоке и передайте его на dispatch_async()
; также передайте dispatch_get_main_queue()
в качестве аргумента очереди.
Ответ 2
Вам необходимо отправить обновление в основной поток:
dispatch_async(dispatch_get_main_queue(), ^{
[self.photoStreamCollectionView reloadData];
});
или в Swift:
dispatch_async(dispatch_get_main_queue(), {
self.photoStreamCollectionView.reloadData()
})
Ответ 3
Apple говорит: вы не должны вызывать этот метод в середине блоков анимации, где элементы вставляются или удаляются. Вставки и удаления автоматически заставляют данные таблиц обновляться соответствующим образом.
В лицо: вы не должны вызывать этот метод в середине любой анимации (включая прокрутку UICollectionView).
Итак, вы можете:
[self.collectionView setContentOffset:CGPointZero animated:NO];
[self.collectionView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
или отметьте уверенность в какой-либо анимации, а затем вызовите reloadData;
или
[self.collectionView performBatchUpdates:^{
//insert, delete, reload, or move operations
} completion:nil];