Сохранение миниатюры в фоновом потоке

Я пытаюсь создать миниатюры (288x288) выбранных фотографий из библиотеки фотографий iPad. У меня есть массив объектов ALAsset, представленных в UITableView, и когда я выбираю строку, отображается увеличенный предварительный просмотр (288x288) этого изображения. Чтобы предотвратить блокировку основного потока, я пытаюсь создать миниатюру в фоновом потоке, а также кэшировать копию миниатюры в файловой системе.

В контроллере представления, когда выбрана строка таблицы, я вызываю loadPreviewImage в фоновом режиме:

- (void)tableView:(UITableView *)tableView
        didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // get the upload object from an array that contains a ALAsset object
    upload = [uploads objectAtIndex:[indexPath row]];

    [self performSelectorInBackground:@selector(loadPreviewImage:)
                           withObject:upload];

}

Я передаю пользовательский объект загрузки, который содержит свойство assetsurl:

- (void)loadPreviewImage:(MyUploadClass*)upload
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    UIImage *preview = [upload previewImage];       
    [self performSelectorOnMainThread:@selector(setPreviewImage:)
                           withObject:preview
                        waitUntilDone:YES];

    [pool release];
}

Это вызывается в основном потоке для отображения эскиза после его загрузки:

- (void)setPreviewImage:(UIImage*)image
{
    self.imageViewPreview.image = image;
    [self layoutSubviews];
}

Это метод MyUploadClass:

- (UIImage *)previewImage
{
    __block UIImage *previewImage = [[UIImage imageWithContentsOfFile:
            [self uploadPreviewFilePath]] retain];

    if (previewImage == nil && asseturl)
    {
        ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
        [library assetForURL:self.asseturl resultBlock:^(ALAsset *asset)
        {                         
            ALAssetRepresentation *rep = [asset defaultRepresentation]; 

            previewImage = [UIImage imageWithCGImage: [rep fullScreenImage]];
            previewImage = [[previewImage resizedImageWithContentMode:UIViewContentModeScaleAspectFit
                                             bounds:CGSizeMake(288, 288)
                               interpolationQuality:kCGInterpolationHigh] retain];

            NSData *previewData = UIImageJPEGRepresentation(previewImage, 1.0); 
            [previewData writeToFile:[self uploadPreviewFilePath] atomically:YES];   
         }
         failureBlock:^(NSError *error){ }];
         [library release];
    } 
    return [previewImage autorelease];
}

Проблема в том, что я всегда получаю nil previewImage в первый раз, и только после кэширования миниатюры я получаю объект изображения. Что я делаю неправильно? Есть ли лучший подход к этой проблеме?


person galexyus    schedule 30.03.2011    source источник


Ответы (1)


Я не совсем понял, как работает блок результатов ALAssetsLibrary, моя ошибка заключалась в том, что я думал, что выполнение является линейным. Оказывается, в моем случае resultBlock выполняется в основном потоке, а остальная часть кода в previewImage выполняется в фоновом потоке. Я получал ноль, потому что previewImage возвращался до того, как resultBlock успел завершить свое выполнение. Я решил проблему, заменив previewImage следующим методом:

- (void) loadPreviewImage:(CGSize)size withTarget:(id)target andCallback:(SEL)callback
{
    NSString *path = [self uploadPreviewFilePath];    
    UIImage *previewImage = [UIImage imageWithContentsOfFile:path];  

    if (previewImage == nil && asseturl)
    {
        ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
        [library assetForURL:self.asseturl resultBlock:^(ALAsset *asset)
        {
            if (asset) {                                  
              ALAssetRepresentation *rep = [asset defaultRepresentation];   

              UIImage *img = [UIImage imageWithCGImage: [rep fullScreenImage]];

              img = [img resizedImageWithContentMode:UIViewContentModeScaleAspectFit
                    bounds:size interpolationQuality:kCGInterpolationHigh];

              NSData *previewData = UIImageJPEGRepresentation(img, 1.0);                            
              [previewData writeToFile:path atomically:YES];     
              [target performSelectorOnMainThread:callback 
                                       withObject:img
                                    waitUntilDone:YES];
          }
       }
      failureBlock:^(NSError *error){ }];                        
      [library release];
  }
  else {
      [target performSelectorOnMainThread:callback withObject:img waitUntilDone:YES];
    }
}
person galexyus    schedule 30.03.2011