NSBlockOperation или NSOperation с блоком ALAsset для отображения изображений библиотеки фотографий с использованием URL-адреса ALAsset

Я задаю этот вопрос относительно моих вопросов. Эффективно отображайте изображения из библиотеки фотографий iPhone и высокоэффективный метод UITableView "cellForRowIndexPath" для привязки изображений PhotoLibrary.

Поэтому я хотел бы попросить, чтобы ответы не дублировались на этот, не читая ниже детали:)

Давайте подойдем к вопросу,

Я подробно изучил вышеупомянутую проблему и нашел документ об очередях операций отсюда.

Поэтому я создал один пример приложения для отображения семи изображений из библиотеки фотографий с использованием очередей операций через блоки ALAsset.

Вот пример примера приложения.

Шаг 1:

В методе NSOperationalQueueViewController viewDidLoad я извлек все URL-адреса ALAsset фотогалереи в массив с именем urlArray,

Шаг 2:

После того, как все URL добавлены в urlArray условие if (group! = nil) будет ложным в assetGroupEnumerator Итак, я создал NSOperationQueue, а затем создал семь UIImageView через for цикл и создал мой NSOperation объект подкласса с соответствующим представлением изображения и URL для каждого и добавил их в NSOperationQueue,

См мой NSOperation подкласс здесь.

Смотрите мой класс реализации (VierwController) здесь.

Давайте подойдем к вопросу.

Это не отображение всех семи изображений последовательно. Некоторые изображения отсутствуют. Пропущенный порядок меняется несколько раз (один раз он не отображает шестой и седьмой, а другой раз он не отображает только второй и третий). В журнале консоли отображается сообщение " Не удалось найти номер фотографии". Тем не менее, URL-адреса регистрируются правильно.

Вы можете увидеть подробности журнала здесь.

Есть ли ошибки в моих занятиях?

Кроме того, когда я просматриваю вышеупомянутую документацию рабочей очереди, я читал о NSBlockOperation, Нужно ли реализовывать NSBlockOperation вместо NSOperation при работе с блоками ALAsset?

NSBlockOperation описание говорит

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

Как я могу реализовать NSBlockOperation с блоком ALAsset относительно моего примера приложения?

Я прошел через вопрос переполнения стека Изучение NSBlockOperation. Тем не менее, я не получил никакой идеи для реализации NSBlockOperation с блоком ALAsset!!

2 ответа

Решение

У вас есть строка в вашем подклассе DisplayImages NSOperation, где вы обновляете пользовательский интерфейс (строка 54 DisplayImages.m):

self.imageView.image = topicImage;

Эта очередь операций выполняется в фоновом потоке, и мы знаем, что вам следует только обновлять состояние пользовательского интерфейса в основном потоке. Поскольку обновление вида представления изображения определенно обновляет пользовательский интерфейс, это можно просто исправить, заключив вызов в:

dispatch_async(dispatch_get_main_queue(), ^{
   self.imageView.image = topicImage;
});

Это помещает асинхронный вызов в основную очередь, чтобы обновить UIImageView с изображением. Он асинхронный, поэтому ваши другие задачи могут планироваться в фоновом режиме, и он безопасен, так как выполняется в главной очереди, которая является основным потоком.

Это учебное пособие о том, "Как получить доступ ко всем изображениям из библиотеки iPhonePhoto с помощью библиотеки ALAsset и показать их на UIScrollView, как iPhoneSimulator". Прежде всего добавить AssetsLibrary.framework к вашему проекту.

Тогда в вашем viewController.h импорт файла #import <AssetsLibrary/AssetsLibrary.h> заголовочный файл

Это ваша viewController.h файл

#import <UIKit/UIKit.h>
#import <AssetsLibrary/AssetsLibrary.h>
#import "AppDelegate.h"

@interface ViewController : UIViewController <UIScrollViewDelegate>
{
    ALAssetsLibrary *assetsLibrary;
    NSMutableArray *groups;
    ALAssetsGroup *assetsGroup;

   // I will show all images on `UIScrollView`
    UIScrollView *myScrollView;

    UIActivityIndicatorView *activityIndicator;

    NSMutableArray *assetsArray;
    // Will handle thumbnail of images 
    NSMutableArray *imageThumbnailArray;
    // Will handle original images 
    NSMutableArray *imageOriginalArray;

    UIButton *buttonImage;
 }

-(void)displayImages;
-(void)loadScrollView;

@end

А это твой viewController.m файл - viewWillAppear:

#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>

@implementation ViewController

- (void)viewWillAppear:(BOOL)animated
{
  [super viewWillAppear:animated];

  assetsArray = [[NSMutableArray alloc]init];
  imageThumbnailArray = [[NSMutableArray alloc]init];
  imageOriginalArray = [[NSMutableArray alloc]init];

  myScrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0.0, 0.0, 320.0, 416.0)];
  myScrollView.delegate = self;
  myScrollView.contentSize = CGSizeMake(320.0, 416.0);
  myScrollView.backgroundColor = [UIColor whiteColor];

  activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
  activityIndicator.center = myScrollView.center;
  [myScrollView addSubview:activityIndicator];
  [self.view addSubview:myScrollView];

  [activityIndicator startAnimating];

}

viewDidAppear:

-(void)viewDidAppear:(BOOL)animated
{
 if (!assetsLibrary) {
        assetsLibrary = [[ALAssetsLibrary alloc] init];
    }
    if (!groups) {
     groups = [[NSMutableArray alloc] init];
  } 
 else {
     [groups removeAllObjects];
 }

 ALAssetsLibraryGroupsEnumerationResultsBlock listGroupBlock = ^(ALAssetsGroup *group, BOOL *stop) {
        //NSLog(@"group %@",group);
        if (group) {
            [groups addObject:group];
         //NSLog(@"groups %@",groups);
     } else {
         //Call display Images method here.
         [self displayImages];
        }
 };
 ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError *error) {
     NSString *errorMessage = nil;
        switch ([error code]) {
         case ALAssetsLibraryAccessUserDeniedError:
            case ALAssetsLibraryAccessGloballyDeniedError:
             errorMessage = @"The user has declined access to it.";
                break;
            default:
             errorMessage = @"Reason unknown.";
             break;
     }
    };
    [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:listGroupBlock failureBlock:failureBlock];

}

А это displayImages: тело метода

-(void)displayImages
{
// NSLog(@"groups %d",[groups count]);
  for (int i = 0 ; i< [groups count]; i++) {
     assetsGroup = [groups objectAtIndex:i];
        if (!assetsArray) {
         assetsArray = [[NSMutableArray alloc] init];
        }
        else {
         [assetsArray removeAllObjects];
     }

     ALAssetsGroupEnumerationResultsBlock assetsEnumerationBlock = ^(ALAsset *result, NSUInteger index, BOOL *stop) {

            if (result) {
                [assetsArray addObject:result];
            }
     };
        ALAssetsFilter *onlyPhotosFilter = [ALAssetsFilter allPhotos];
        [assetsGroup setAssetsFilter:onlyPhotosFilter];
        [assetsGroup enumerateAssetsUsingBlock:assetsEnumerationBlock];

    }

    //Seprate the thumbnail and original images
    for(int i=0;i<[assetsArray count]; i++)
    {
        ALAsset *asset = [assetsArray objectAtIndex:i];
        CGImageRef thumbnailImageRef = [asset thumbnail];
        UIImage *thumbnail = [UIImage imageWithCGImage:thumbnailImageRef];
        [imageThumbnailArray addObject:thumbnail];

        ALAssetRepresentation *representation = [asset defaultRepresentation];
        CGImageRef originalImage = [representation fullResolutionImage];
        UIImage *original = [UIImage imageWithCGImage:originalImage];
        [imageOriginalArray addObject:original];
    }

    [self loadScrollView];
}

Теперь у вас есть два array один imageThumbnailArray а другой imageOriginalArray, использование imageThumbnailArray для показа на UIScrollView для которого ваша прокрутка не будет медленной.... и использовать imageOriginalArray для расширенного предварительного просмотра изображения.

Метод loadScrollView: это как изображения на UIScrollView как iPhoneSimulator

#pragma mark - LoadImages on UIScrollView
-(void)loadScrollView
{
    float horizontal = 8.0;
    float vertical = 8.0;

    for(int i=0; i<[imageThumbnailArray count]; i++)
    {
        if((i%4) == 0 && i!=0)
        {
            horizontal = 8.0;
            vertical = vertical + 70.0 + 8.0;
        }

        buttonImage = [UIButton buttonWithType:UIButtonTypeCustom];
        [buttonImage setFrame:CGRectMake(horizontal, vertical, 70.0, 70.0)];
        [buttonImage setTag:i];
    [   buttonImage setImage:[imageThumbnailArray objectAtIndex:i] forState:UIControlStateNormal];
        [buttonImage addTarget:self action:@selector(buttonImagePressed:) forControlEvents:UIControlEventTouchUpInside];
        [myScrollView addSubview:buttonImage];
        horizontal = horizontal + 70.0 + 8.0;

    }

    [myScrollView setContentSize:CGSizeMake(320.0, vertical + 78.0)];
    [activityIndicator stopAnimating];
    [activityIndicator removeFromSuperview];
}

И здесь вы можете найти, какое изображение button была нажата -

#pragma mark - Button Pressed method
-(void)buttonImagePressed:(id)sender
{
     NSLog(@"you have pressed : %d button",[sender tag]);   
}

Надеюсь, этот урок поможет вам и многим пользователям, которые ищут то же самое. Спасибо!

Другие вопросы по тегам