заполнение tableview изображениями камеры

Я пытаюсь заполнить изображения из камеры в табличном представлении.

в 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 и, похоже, не использую его правильно. Любая помощь в этом вопросе приветствуется.


person CalZone    schedule 01.06.2013    source источник
comment
Сбои приложений — очень плохое объяснение. Можете ли вы предоставить журналы сбоев и сообщения об ошибках? Ваше приложение может давать сбой по множеству причин.   -  person Bruno Koga    schedule 01.06.2013
comment
Ряд вещей не так с вашим кодом, но перед этим - вы уверены, что библиотека Assets является потокобезопасной?   -  person maroux    schedule 01.06.2013
comment
@property (nonatomic, readwrite) ALAssetsLibrary *assetsLibrary; и @property (nonatomic, readwrite) ALAssetsGroup *assetGroup;   -  person CalZone    schedule 01.06.2013


Ответы (2)


Вам нужно вызвать [self.tableView reloadData] после завершения блока перечисления в viewDidLoad и заполнения self.assetGroup. Блок перечисления выполняется асинхронно, поэтому reloadData вызывается до завершения блока, а в обратных вызовах делегата табличного представления ваша группа активов не содержит данных. К тому времени, когда вы начнете прокручивать, свойство будет заполнено, и вы начнете видеть изображения.

Я не видел документации Apple, в которой объясняется, как определить конец блока перечисления, но эти два принятых ответа указывают на то, что значение группы будет равно нулю, когда перечисление закончится.

селектор завершения enumerateGroupsWithTypes для iPhone Узнать, когда мой асинхронный вызов завершен

Поэтому поместите условие 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. Этот блок также будет выполняться асинхронно. Нет необходимости отправлять его в фоновую очередь.

person Kedar    schedule 01.06.2013
comment
Чертовски круто!! Большое спасибо, приятель. Это была именно моя проблема. - person CalZone; 01.06.2013
comment
Привет, Кедар, я все еще получаю предупреждение о памяти. Есть идеи, как это исправить? - person CalZone; 02.06.2013
comment
Вы видите предупреждающее сообщение в консоли? Или вызывается didReceiveMemoryWarning. - person Kedar; 02.06.2013

Измените строку в методе cellforRowAtIndexPath с:

cell.imageView.image = img;

to:

dispatch_async(dispatch_get_main_queue(), ^{
    cell.imageView.image = img;
});

Каждое изменение в представлениях должно быть реализовано в основном потоке, если вы измените изображение своей ячейки в другом потоке (то, что вы сейчас делаете), представление ячейки не изменится.

person edzio27    schedule 01.06.2013
comment
Производительность немного лучше, но ячейки не загружаются, они загружаются только тогда, когда я начинаю прокручивать. - person CalZone; 01.06.2013
comment
Вы пытались перезагрузить ячейку после установки изображения? [self.tableView reloadRowsAtIndexPaths: indexArray withRowAnimation: UITableViewRowAnimationFade]; - person edzio27; 01.06.2013
comment
Как вы думаете, причиной этого может быть тот факт, что cellforrowAtIndexPath вызывается перед viewDidload? и так как я создаю группу в viewdidload, она недоступна для cellForRowAtIndexPath - person CalZone; 01.06.2013