在我的申请中。我在主线程上得到了一堆图像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];
}
}
这让我在0.2秒内获得了大约300个网址。然后我尝试异步加载每个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;
}
集合加载非常快,也是异步加载(我可以在加载内容时滚动,并且会看到弹出的新图像)。问题是当我向上和向下滚动时,即使在所有图像都已加载之后,事物仍然以随机顺序重新排列:我将查看一个单元格,然后它将其图像与另一个单元格切换为没有明显的理由。为什么会这样?
答案 0 :(得分:0)
我发现了一个非常简单的解决方案:
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
方法。即使只是在视野中。