#asynchronous #uicollectionview #uicollectionviewcell
#асинхронный #uicollectionview #uicollectionview ячейка #uicollectionviewcell
Вопрос:
В моем приложении. Я получаю кучу URL-адресов изображений в основном потоке следующим образом:
- (void)viewDidLoad
{
[super viewDidLoad];
[self populateCollection];
}
- (void)populateCollection
{
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:[MTGJSONBridge JSONURLWithSetCode:@"LEA"]]
options:kNilOptions
error:nil];
NSLog(@"Json: %@", json);
NSArray *cards = json[@"cards"];
_URLs = [NSMutableArray arrayWithCapacity:cards.count];
for (NSDictionary *card in cards)
{
NSURL *imageURL = [MTGJSONBridge URLWithSetCode:@"LEA" cardName:card[@"imageName"]];
if (imageURL)
[_URLs addObject:imageURL];
}
}
Это дает мне около 300 URL-адресов за 0,2 секунды. Затем я пытаюсь асинхронно загружать изображения с каждого URL-адреса следующим образом:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = @"reuseIdentifier";
MTGCardCollectionCell *cell = (MTGCardCollectionCell *)[collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
NSURL *url = _URLs[indexPath.row];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// No explicit autorelease pool needed here.
// The code runs in background, not strangling
// the main run loop.
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
dispatch_sync(dispatch_get_main_queue(), ^{
// This will be called on the main thread, so that
// you can update the UI, for example.
cell.imageView.image = image;
});
});
return cell;
}
У меня также есть это:
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return _URLs.count;
}
Коллекция загружается очень быстро и к тому же асинхронно (я могу прокручивать во время загрузки, и я вижу, как появляются новые изображения). Проблема в том, что при прокрутке вверх и вниз, даже после загрузки всех изображений, объект продолжает перестраиваться в случайном порядке: я смотрю на одну ячейку, а затем ее изображение переключается на другое без видимой причины. Почему это происходит?
Ответ №1:
Я обнаружил очень простое решение:
if (cell.imageView.image == nil)
{
NSURL *url = _URLs[indexPath.row];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// No explicit autorelease pool needed here.
// The code runs in background, not strangling
// the main run loop.
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
dispatch_sync(dispatch_get_main_queue(), ^{
// This will be called on the main thread, so that
// you can update the UI, for example.
cell.imageView.image = image;
});
});
}
else
{
NSLog(@"Cell image isn't nil");
}
Все, что мне нужно сделать, это проверить, не загружена ли ячейка. Оказывается, - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
метод вызывается всякий раз, когда в поле зрения попадает ячейка. Даже если это было только в представлении.