带有ALAsset Block的NSBlockOperation或NSOperation使用ALAsset URL显示照片库图像

时间:2012-07-20 14:00:12

标签: iphone nsoperation nsoperationqueue alassetslibrary nsblockoperation

我问的问题是Display photolibrary images in an effectual way iPhone Highly efficient UITableView "cellForRowIndexPath" method to bind the PhotoLibrary images

所以我想请求在没有阅读以下细节的情况下,答案不会重复到这个答案:)

让我们来讨论这个问题,

我已经详细研究了上述问题,我从here找到了关于操作队列的文档。

所以我创建了一个示例应用程序,通过ALAsset块使用操作队列显示七个照片库图像。

以下是示例应用程序详细信息。

第1步:

在NSOperationalQueueViewController viewDidLoad 方法中,我已将所有照片库ALAsset URLs检索到名为urlArray的数组中。

第2步:

将所有网址添加到urlArray后, if(group!= nil)条件在assetGroupEnumerator中将为false,因此我创建了一个{{ 1}},然后通过NSOperationQueue循环创建了7个UIImageView,并使用相应的图像视图 URL 创建了我的for子类对象每个添加NSOperation

请参阅我的NSOperationQueue子类here

查看我的实现(VierwController)类 here

让我们来讨论这个问题。

它不会始终显示所有七个图像。一些图像丢失了。丢失的顺序多次改变(一次不显示第六和第七次,另一次不显示第二次和第三次)。控制台日志显示无法找到照片图片号。但是,URL已正确记录。

您可以查看日志详细信息here

我班上有错误吗?

另外,当我浏览上面提到的operational queue文档时,我已经阅读了NSOperation。在处理ALAsset块时,是否需要实现NSBlockOperation而不是NSBlockOperation

NSOperation说明

  

您原样使用的类,用于执行一个或多个块对象   同时。因为它可以执行多个块,一个块   操作对象使用组语义进行操作;只有当所有的   关联块已完成执行是操作本身   考虑完了。

如何针对我的示例应用程序实现带有ALAsset块的NSBlockOperation

我已经完成了Stack Overflow问题 Learning NSBlockOperation 。但是,我没有想到用ALAsset块实现NSBlockOperation !!

2 个答案:

答案 0 :(得分:5)

这是关于“如何使用ALAsset库从iPhonePhoto库访问所有图像并在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。 使用imageThumbnailArrayUIScrollView上显示您的滚动速度不会很慢....并使用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]);   
}

希望本教程能够帮助您和许多搜索相同内容的用户..谢谢!

答案 1 :(得分:4)

您在DisplayImages NSOperation子类中有一行更新UI(DisplayImages.m第54行):

self.imageView.image = topicImage;

此操作队列在后台线程上运行,我们知道您应该只更新主线程上的UI状态。由于更新图像视图的视图肯定是在更新UI,因此可以通过使用:

包装调用来简单地修复此问题
dispatch_async(dispatch_get_main_queue(), ^{
   self.imageView.image = topicImage;
});

这会在主队列上进行异步调用,以使用映像更新UIImageView。它是异步的,所以你的其他任务可以在后台安排,并且它在主队列上运行是安全的 - 这是主线程。