填充tableview与相机胶卷图像
问题描述:
我想从tableview中的相机胶卷填充图像。我创建一个资产组。填充tableview与相机胶卷图像
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.assetsLibrary = [[ALAssetsLibrary alloc] init];
[self.assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
if(nil!=group){
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
self.assetGroup = group;
NSLog(@"%d images found", self.assetGroup.numberOfAssets);
}
} failureBlock:^(NSError *error) {
NSLog(@"block fucked!");
}];
[self.tableView reloadData];
}
在CellForRowAtIndexPath
,我使用GCD背景队列各自索引处,以用图像的细胞。
static NSString *CellIdentifier = @"Cell";
dispatch_queue_t imgLoadQueue = dispatch_queue_create("Thumb loader", NULL);
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
dispatch_async(imgLoadQueue, ^{
[self.assetGroup enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:indexPath.row] options:0 usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if (nil != result) {
ALAssetRepresentation *repr = [result defaultRepresentation];
UIImage *img = [UIImage imageWithCGImage:[repr fullResolutionImage]];
cell.imageView.image = img;
}
}];
});
return cell;
问题是,初始单元格是空的。图像只有在我开始滚动后才开始加载。而且,一旦我滚动,应用程序就会崩溃。我对GCD相当陌生,似乎没有正确使用它。对此事的任何帮助表示赞赏。在你的cellForRowAtIndexPath方法
答
您需要在viewDidLoad
中的枚举块完成并且已填充self.assetGroup
之后调用[self.tableView reloadData]
。枚举块是异步执行的,因此在块完成之前调用reloadData并在表视图中委托回调您的assetGroup不包含任何数据。当你开始滚动时,该属性被填充,你开始看到图像。
我还没有看到解释如何检测枚举块结束的苹果文档,但这两个接受的答案表明,枚举结束时,组值将为零。
iPhone enumerateGroupsWithTypes finishing selector Find out when my asynchronous call is finished
所以把一个else条件在组枚举块 -
if(nil!=group){
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
self.assetGroup = group;
NSLog(@"%d images found", self.assetGroup.numberOfAssets);
}
else
[self.tableView reloadData];
取出reloadData枚举块之后被调用。
尝试将CellForRowAtIndexPath中的枚举块取出GCD队列。该块也将异步执行。无需将其分派到后台队列。
答
更改行从:
cell.imageView.image = img;
到:
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image = img;
});
在视图中的每个变化,必须在主线程中实现,如果你在其他线程改变你的细胞图像(什么你目前的做)单元格演示文稿不会改变。
“应用程序崩溃”是一个非常糟糕的解释。你能提供崩溃日志和错误信息吗?你的应用程序可能会由于许多不同的原因而崩溃。 –
您的代码存在一些错误,但在此之前 - 您确定Assets库是线程安全的吗? – Mar0ux
'@property(nonatomic,readwrite)ALAssetsLibrary * assetsLibrary;'和 '@property(nonatomic,readwrite)ALAssetsGroup * assetGroup;' – CalZone