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]);
}
Надеюсь, этот урок поможет вам и многим пользователям, которые ищут то же самое. Спасибо!