• Creating An Image Gallery Like Over – Part 1

    19 February 2016

    Screen Shot 2013-08-09 at 8.36.42 PM

    For this tutorial, I will start with a Fresh iOS6 View-Based application that uses Storyboards and ARC. Also note that I will be optimizing for the iPhone 5 resolution.  You are free to make the tweaks necessary to deploy on the iPhone 4 and 4S.

    Here is a breakdown of what we will cover in this part:

    1. Creating a UICollectionView inside of Storyboard
    2. Using the ALAssetsLibrary to fetch photos from the user’s Camera Roll
    3. Displaying the ALAssets inside of the UICollectionView

    1. Preparing The IBOutlets

    Start by opening up ViewController.m and replacing the @interface declaration at the top with the following code:

    @interface ViewController ()<UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout>
    @property(nonatomic, weak) IBOutlet UICollectionView *collectionView;
    @end

    This will declare the IBOutlet needed to hook up the main UICollectionView that we will be using to display the user’s photos.  I have also set up our class to be a UICollectionViewDataSourceUICollectionViewDelegate, andUICollectionViewDelegateFlowLayout. This is necessary when interfacing with the UICollectionView.

    2. Setting Up The UICollectionView In Storyboard

    Open up MainStoryboard.storyboard and drag a UICollectionView on to your view ensuring that it stretches the entire screen.

    Screen Shot 2013-07-21 at 8.44.02 PM

    Then, Control-Click and drag from the UICollectionView to your ViewController Object and set it as the delegate and datasource.

    Screen Shot 2013-07-21 at 8.41.29 PM

    Finally, Control-Click and drag from View Controller to Collection View and selected collectionView to make the IBOutlet connection.

    Screen Shot 2013-07-21 at 8.45.05 PM

    Now, we need to give a Cell Identifier to the UICollectionViewCell so that we can reference it in code.  Click on the default cell inside of the UICollectionView and open the Attributes Inspector. For the Identifier type in PhotoCell. The cell might be a little tricky to see as its background color is clear, but it’s there. Simply click in the top left corner of theUICollectionView.

    Screen Shot 2013-07-21 at 9.13.08 PM

    Now that the UICollectionView has been set up, it’s time to fetch the photos from the user’s photo library.

    If you are using the simulator, make sure to populate the Photo Gallery with images from the web. Simply open up a browser, do a Google Image Search, and click and hold on various images. You should have an option from the menu that pops up to save the images to your camera roll.
    
    Finally, open up the Photos app on the simulator to initialize the Assets Library.

    3. Fetching ALAssets (user photos) From The ALAssets Library

    In order to interface with the user’s photo library, we must first import the AssetsLibrary.framework framework.  To do this, click on your project in the sidebar, select the Target, then click Build Phases, expand the Link Binary With Libraries section and click the button.  Do a search for Assset and then double click on AssetsLibrary.framework.

    Screen Shot 2013-07-21 at 8.57.37 PM

    It should now be added to your project and ready to use.  Now that it has been linked, we must import it into the ViewController.m file.  Open up ViewController.m and add the following import to the top of the file:

    #import <AssetsLibrary/AssetsLibrary.h>

    Before we can fetch the user’s photos, we need to set up an NSArray to put them in.  Add the following line within the @interface declaration at the top.

    @property(nonatomic, strong) NSArray *assets;

    Now, add the following method to your class:

    + (ALAssetsLibrary *)defaultAssetsLibrary
    {
        static dispatch_once_t pred = 0;
        static ALAssetsLibrary *library = nil;
        dispatch_once(&pred, ^{
            library = [[ALAssetsLibrary alloc] init];
        });
        return library;
    }

    This is a static method that creates a static instance to the ALAssetsLibrary.  The reason this is needed is, when we enumerate the ALAssets in the next method, it seems that the assets get released immediately and otherwise wouldn’t be able to be used in the rest of the application. I will explain this a little more in a moment.

    Head over to viewDidLoad and add the following code:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
     
        _assets = [@[] mutableCopy];
        __block NSMutableArray *tmpAssets = [@[] mutableCopy];
        // 1
        ALAssetsLibrary *assetsLibrary = [ViewController defaultAssetsLibrary];
        // 2
        [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
            [group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
                if(result)
                {
                    // 3
                    [tmpAssets addObject:result];
                }
            }];
     
            // 4
            //NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"date" ascending:NO];
            //self.assets = [tmpAssets sortedArrayUsingDescriptors:@[sort]];
            self.assets = tmpAssets;
     
            // 5
            [self.collectionView reloadData];
        } failureBlock:^(NSError *error) {
            NSLog(@"Error loading images %@", error);
        }];
    }

    1. Grab our static instance of the ALAssetsLibrary
    2. Enumerate through all of the ALAssets (photos) in the user’s Asset Groups (Folders)
    3. Enumerate each folder and add it’s ALAssets to the temporary array
    4. Sort the assets list by date (this won’t work yet, but I will show you how to fix later). For now this code is commented out and the Assets will be sorted however they come out.
    5. Reload the UICollectionView (this won’t work yet as we haven’t set up the delegate methods)

    Now that we have an NSArray populated with ALAssets, let’s set up the delegate methods for the UICollectionView in order to populate it with data.

    4. Populating the UICollectionView With Data

    UICollectionView functions much like a UITableView having delegate and datasource methods.  Add the following methods to your ViewController class to populate the view.

    #pragma mark - collection view data source
     
    - (NSInteger) collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
    {
        return self.assets.count;
    }
     
    - (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        UICollectionViewCell *cell = (UICollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"PhotoCell" forIndexPath:indexPath];
     
        ALAsset *asset = self.assets[indexPath.row];
        //cell.asset = asset;
        cell.backgroundColor = [UIColor redColor];
     
        return cell;
    }
     
    - (CGFloat) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
    {
        return 4;
    }
     
    - (CGFloat) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
    {
        return 1;
    }

    This code should be fairly straight forward if you have ever worked with a UITableView. The only lines to note are where ‘cell.asset = asset’ is commented out and we set the cell’s background color to red.  We will uncomment that line when we create a custom cell to display the image (for now it won’t).  I have also set the background color to red so that you can see that the number of cells is actually corresponding to the number of photos in the camera roll.

    Build and Run!

    Let’s take a break to do a build and run to see what happens.  If you have hooked everything up correctly, you should see a black screen with red squares on it with a count equalling the number of photos in the user’s library.

    Screen Shot 2013-07-21 at 9.26.07 PM

    Not too exciting, however it shows that we are displaying a number of cells corresponding to the number of photos in the user’s asset library.  At least it’s showing that you have done something.  The next step is to create a custom UICollectionViewCell that actually displays the photos, which we will do next time.

Comments

Comments closed on this post.