Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
268 views
in Technique[技术] by (71.8m points)

iphone - NSBlockOperation or NSOperation with ALAsset Block to display photo-library images using ALAsset URL

I am asking this question regarding my questions Display photolibrary images in an effectual way iPhone and Highly efficient UITableView "cellForRowIndexPath" method to bind the PhotoLibrary images.

So I would like to request that answers are not duplicated to this one without reading the below details :)

Let's come to the issue,

I have researched detailed about my above mentioned issue, and I have found the document about operation queues from here.

So I have created one sample application to display seven photo-library images using operation queues through ALAsset blocks.

Here are the sample application details.

Step 1:

In the NSOperationalQueueViewController viewDidLoad method, I have retrieved all the photo-gallery ALAsset URLs in to an array named urlArray.

Step 2:

After all the URLs are added to the urlArray, the if(group != nil) condition will be false in assetGroupEnumerator, so I have created a NSOperationQueue, and then created seven UIImageView's through a for loop and created my NSOperation subclass object with the corresponding image-view and URL for each one and added them in to the NSOperationQueue.

See my NSOperation subclass here.

See my implementation (VierwController) class here.

Let's come to the issue.

It not displaying all the seven images consistently. Some of the images are missing. The missing order is changing multiple times (one time it doesn't display the sixth and seventh, and another time it doesn't display only the second and third). The console log displays Could not find photo pic number. However, the URLs are logged properly.

You can see the log details here.

Are there any mistakes in my classes?

Also, when I go through the above mentioned operational queue documentation, I have read about NSBlockOperation. Do I need to implement NSBlockOperation instead of NSOperation while dealing with ALAsset blocks?

The NSBlockOperation description says

A class you use as-is to execute one or more block objects concurrently. Because it can execute more than one block, a block operation object operates using a group semantic; only when all of the associated blocks have finished executing is the operation itself considered finished.

How can I implement the NSBlockOperation with ALAsset block regarding my sample application?

I have gone through Stack Overflow question Learning NSBlockOperation. However, I didn't get any idea to implement the NSBlockOperation with ALAsset block!!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is the tutorial about "How to access all images from iPhonePhoto Library using ALAsset Library and show them on UIScrollView like iPhoneSimulator" . First of all add AssetsLibrary.framework to your project.

Then in your viewController.h file import #import <AssetsLibrary/AssetsLibrary.h> header file.

This is your viewController.h file

#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

And this is your viewController.m file - 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];

}

And this is displayImages: method body

-(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];
}

Now you have two array one is imageThumbnailArray and another is imageOriginalArray. Use imageThumbnailArray for showing on UIScrollView for which your scrolling will not be slow.... And use imageOriginalArray for an enlarged preview of image.

'loadScrollView:' method, This is how to images on UIScrollView like 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];
}

And here you can find which image button has been clicked -

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

Hope this tutorial will help you and many users who search for the same.. Thank you!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...