【问题标题】:NSBlockOperation or NSOperation with ALAsset Block to display photo-library images using ALAsset URLNSBlockOperation 或 NSOperation with ALAsset Block 使用 ALAsset URL 显示照片库图像
【发布时间】:2012-07-19 19:44:50
【问题描述】:

我问这个问题是关于我的问题Display photolibrary images in an effectual way iPhoneHighly efficient UITableView "cellForRowIndexPath" method to bind the PhotoLibrary images

所以我想请求不要在不阅读以下详细信息的情况下将答案复制到此答案:)

让我们来解决问题,

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

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

这里是示例应用程序的详细信息。

第 1 步:

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

第 2 步:

所有的url都添加到urlArray之后,assetGroupEnumerator中的if(group != nil)条件会为假,所以我创建了一个NSOperationQueue,然后通过for 循环创建了七个 UIImageView 并创建了我的NSOperation 子类对象,每个对象都有相应的 image-viewURL添加 他们在NSOperationQueue.

查看我的NSOperation 子类here

查看我的实现 (VierwController) 类 here

让我们来解决问题。

它没有一致地显示所有七个图像。部分图像丢失。丢失的顺序多次更改(一次不显示第六和第七,另一次不显示第二和第三)。控制台日志显示找不到照片图片编号。但是,URL 已正确记录。

可以查看日志详情here

我的课有什么错误吗?

此外,当我浏览上述operational queue 文档时,我已经阅读了有关NSBlockOperation 的信息。在处理 ALAsset 块时,我是否需要实现 NSBlockOperation 而不是 NSOperation

NSBlockOperation 描述说

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

关于我的示例应用程序,如何使用 ALAsset 块实现 NSBlockOperation

我已经解决了 Stack Overflow 问题Learning NSBlockOperation。但是,我不知道用 ALAsset 块实现NSBlockOperation!!

【问题讨论】:

    标签: iphone nsoperation nsoperationqueue alassetslibrary nsblockoperation


    【解决方案1】:

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

    self.imageView.image = topicImage;
    

    此操作队列在后台线程上运行,我们知道您应该只在主线程上更新 UI 的状态。由于更新图像视图的视图肯定会更新 UI,因此可以通过以下方式简单地解决此问题:

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

    这会在主队列上进行异步调用,以使用图像更新 UIImageView。它是异步的,因此您的其他任务可以在后台安排,而且它运行在主队列(即主线程)上是安全的。

    【讨论】:

    • 太棒了...“我看到他之前说过“你应该只在主线程上更新 UI 的状态”。现在我很好地理解了它的含义 :).. 感谢 abizern。u rockzzzz ...
    【解决方案2】:

    这是关于“如何使用 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]);   
    }
    

    希望本教程对您和许多搜索相同内容的用户有所帮助。谢谢!

    【讨论】:

    • 感谢您的快速回复。我要求使用他们的 ALAsset url 显示照片库图像。在启动应用程序之前,让我们考虑一下我的数据库中的所有照片库图像 url。出于上述(您的回答)目的,我可以通过“UIImagePickerController”显示照片库图像,而无需使用 ALSAsset。正确的?所以请发布“使用他们的 ALAsset url 显示照片库图像的答案。我想你可以回答。
    • UIImagePickerController 在哪里使用????,....nslog assetsArray .. 你会看到它包含所有图片的 url....
    • 对不起,如果我错了:)。让澄清一件事。我认为 assetsArray 数组包含 ALAsset 对象。不是 NSUrl 或资产 URL。对吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-19
    • 1970-01-01
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多