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

后端 未结 2 1202
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-10 22:40

I am asking this question regarding my questions Display photolibrary images in an effectual way iPhone and Highly efficient UITableView \"cellForRowIndexPath\" method t

相关标签:
2条回答
  • 2020-12-10 23:07

    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!

    0 讨论(0)
  • 2020-12-10 23:17

    You have a line in your DisplayImages NSOperation subclass where you update the UI (DisplayImages.m line 54):

    self.imageView.image = topicImage;
    

    This operation queue is running on a background thread, and we know that you should only update the state of the UI on the main thread. Since updating the view of an image view is definitely updating the UI, this can be simply fixed by wrapping the call with:

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

    This puts an asynchronous call on the main queue to update the UIImageView with the image. It's asynchronous so your other tasks can be scheduled in the background, and it's safe as it is running on the main queue - which is the main thread.

    0 讨论(0)
提交回复
热议问题