我有UICollectionView
我正在加载多个图片。从我读过的内容来看,为了将正确的图像与每个单元格匹配,我需要将UIImageView
子类化并在那里获取图像。因为每次我collectionView reloadData
,一些图像都会重复,并且它们都会出现故障。但我不确定如何做到这一点,并没有找到任何教程。我正在使用Parse作为数据库。
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
albumImageCell *cell = (albumImageCell *) [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[albumImageCell alloc]init];
}
PFObject *temp = [_dataArray objectAtIndex:indexPath.row];
PFFile *file = [temp objectForKey:@"imageThumbnail"];
if (![cell.hasImage isEqualToString:@"YES"]) {
dispatch_async(imageQueue, ^{
NSData *data = [file getData];
if (data) {
UIImage *image = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^(void){
cell.imageView.image = image;
cell.hasImage = @"YES";
});
}
});
}
return cell;
}
答案 0 :(得分:5)
解决此问题的一种方法是,一旦您重新回到主队列,就会再次查询单元格的集合视图。这段代码应该有效:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
albumImageCell *cell = (albumImageCell *) [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[albumImageCell alloc]init];
}
PFObject *temp = [_dataArray objectAtIndex:indexPath.row];
PFFile *file = [temp objectForKey:@"imageThumbnail"];
if (![cell.hasImage isEqualToString:@"YES"]) {
dispatch_async(imageQueue, ^{
NSData *data = [file getData];
if (data) {
UIImage *image = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^(void){
// cellAgain will be the actual cell at that index path, if it is visible.
// If it is not visible, cellAgain will be nil.
albumImageCell *cellAgain = [collectionView cellForItemAtIndexPath:indexPath];
cellAgain.imageView.image = image;
cellAgain.hasImage = @"YES";
});
}
});
}
return cell;
}
答案 1 :(得分:0)
我做了一个小教程'回答this question。虽然问题涉及核心数据,但我的答案适用于任何数据源,因此您应该能够适应您的用例。
当你回到主队列时,你要注意的一件事是内部块。鉴于您不知道到达该点需要多长时间,该单元格可能不再与该图像相关(可能已被重用),因此您需要进行一些额外的检查......
(a)是否还需要图片?
if ([[tableView indexPathsForVisibleRows] containsObject:indexPath])
(b) 单元格是图像的正确单元格吗?
UITableViewCell * correctCell = [self.tableView cellForRowAtIndexPath:indexPath];
虽然本教程仍然有效,但我现在倾向于进一步抽象。由于viewController必须处理UIKit和Core Data等线程不安全的实体,因此最好在主线程上保留所有 viewController代码。背景队列抽象应该在较低级别进行,优选地在模型代码中进行。
答案 2 :(得分:0)
我最终做的是继承UIImaveView
,然后将图像文件传递到cellForRow
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
albumImageCell *cell = (albumImageCell *) [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[albumImageCell alloc]init];
}
PFObject *temp = [_dataArray objectAtIndex:indexPath.row];
PFFile *file = [temp objectForKey:@"imageThumbnail"];
[cell.imageView setFile:file];
return cell;
}
然后在customImageView
-
- (void) setFile:(PFFile *)file {
NSString *requestURL = file.url; // Save copy of url locally (will not change in block)
[self setUrl:file.url]; // Save copy of url on the instance
self.image = nil;
[file getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
UIImage *image = [UIImage imageWithData:data];
if ([requestURL isEqualToString:self.url]) {
[self setImage:image];
[self setNeedsDisplay];
}
} else {
NSLog(@"Error on fetching file");
}
}];
}
但每次用户滚动到新单元格时,这都会获取数据。因此我仍然试图找出如何将特定图像与单元格匹配,而不是每次都获取数据。