Заполнение таблицы с помощью изображений с камеры
Я пытаюсь заполнить изображения с камеры в виде таблицы.
в ViewDidLoad
Я создаю группу активов.
- (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 и, похоже, не правильно его использую. Любая помощь в этом вопросе приветствуется.
2 ответа
Вам нужно позвонить [self.tableView reloadData]
после блока перечисления в viewDidLoad
завершается и self.assetGroup
был заселен. Блок перечисления выполняется асинхронно, поэтому reloadData вызывается до того, как блок завершен, и в ответах на вызовы делегата табличного представления ваша assetGroup не содержит данных. К тому времени, когда вы начнете прокручивать, свойство заполнится, и вы начнете видеть изображения.
Я не видел документации Apple, которая объясняет, как определить конец блока перечисления, но эти два принятых ответа указывают, что значение группы будет нулевым, когда перечисление закончится.
iPhone enumerateGroupsWithTypes Завершение выбора Узнайте, когда мой асинхронный вызов завершен
Поэтому поместите условие 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. Этот блок также будет выполняться асинхронно. Нет необходимости отправлять его в фоновую очередь.
Измените строку в вашем методе cellforRowAtIndexPath с:
cell.imageView.image = img;
чтобы:
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image = img;
});
Каждое изменение в представлениях должно быть реализовано в главном потоке, если вы измените изображение своей ячейки в другом потоке (то, что вы делаете в данный момент), представление ячейки не изменится.