Have you ever wondered how some of Apple’s apps like iBooks have these unique “shelf” stylings, groups and rows of products or photos? Ever wanted to duplicate that functionality? Now, the process is much easier.

Something new and exciting available in iOS 6 is UICollectionViewUICollectionView is similar to UITableView, except think of them as table views on steroids. If you need something a bit more exciting than just plain rows, UICollectionView can help. In fact, you can even create advanced layouts like circles, different cell sizes for each item (think horizontal or vertical photo-books), or even adjust their transforms on a cell-by-cell basis. But first, lets learn a bit more about UICollectionView.

Apple made UICollectionView very easy to use. The concept is simple and each UICollectionView has three main components:

  1. Cells: cells are the content you wish to display, and inherits their format (bookshelf, circle, line, etc) from a layout that you specify
  2. Supplementary Views: supplementary views are views like labels and section headers/footers
  3. Decoration Views: decoration views are just that – decorations like a bookshelf graphic or a background

Setting up a collection view is very similar to a table view. The first step is to tell your view controller that you conform to the UICollectionViewDelegateas demonstrated below:

@interface ViewController : UICollectionViewController 

Since UICollectionView uses the QuartzCore framework, you need to add that into the project as well.

With the view defined, jump over to the implementation file and implement the numberOfSectionsInCollectionView: andcollectionView:numberOfItemsInSection: delegate methods. This tells the collection view how many sections are included in the view and how many items are in each section, respectively.

-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return 4;
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section {
    return 4;
 - (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath; {
    Cell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"MY_CELL" forIndexPath:indexPath];
    cell.label.text = [NSString stringWithFormat:@"%d",indexPath.item];
    return cell;

Something else that is new with UICollectionView is the modification to how cells are initialized and reused. We no longer have to instantiate the cell because Apple takes care of that for us. You may have noticed a few differences with the code above. Namely, the lack of a (!cell) in thecellForItemAtIndexPath:, and this code in the viewDidLoad:

[self.collectionView registerClass:[Cell class] forCellWithReuseIdentifier:@"MY_CELL"];

Now, we have a basic collection view setup, but as you can see it doesn’t look at all like a finished product. In fact, if you built the app right now, the screen would just be blank.

First, we want to tell the view what each of its cells looks like. So lets create and add a Cell.h/.m file to the project. Then add a single property named label to our Cell, which will be used to display a numerical value on the cell:

@interface Cell : UICollectionViewCell
@property (retain, nonatomic) UILabel* label;

and then be sure to initialize the label in the cells implementation like so.

@implementation Cell
- (id)initWithFrame:(CGRect)frame
    self = [super initWithFrame:frame];
    if (self) {
        self.label = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, frame.size.width, frame.size.height)];
        self.label.textAlignment = NSTextAlignmentCenter;
        self.label.textColor = [UIColor blackColor];
        self.label.font = [UIFont boldSystemFontOfSize:35.0];
        self.label.backgroundColor = [UIColor whiteColor];
        [self.contentView addSubview:self.label];;
    return self;

So, now we have a custom cell that displays a centered label. The last piece is to tell the UICollectionView what layout you want to display the cells in. For that, create a new class named CollectionViewLayout.h/.m that subclasses UICollectionViewFlowLayout. A UICollectionViewFlowLayout is a simple layout that allows the views to “Flow”, whether horizontally or vertically. It organizes items in a grid, flowing the items from each row or column to the next, as many as will fit in each. Cells do not need to be the same size to utilize UICollectionViewFlowLayout.

There are also a few other methods to register the cell:

  • -(void)registerClass:forCellWithReuseIdentifier:
  • -(void)registerClass:forSupplementaryViewOfKind:withReuseIdentifier:
  • -(void)registerNib:forCellWithReuseIdentifier:
  • -(void)registerNib:forSupplementaryViewOfKind:withReuseIdentifier:

the registerNib function is very interesting, because now you can make your own custom NIB file that is reused as a cell, all with a few lines of code – and with a completely new layout.

The interface definition is straight-forward as you can see below.

@interface CollectionViewLayout : UICollectionViewFlowLayout

The meat of creating a nice looking collection view is in the layout itself. As you can see in the following example, there are a number of configurable options available to you. You can set the padding, margins, item sizes, scrolling direction and more.

#import "CollectionViewLayout.h"
@implementation CollectionViewLayout
-(id)init {
    self = [super init];
    if (self) {
        self.itemSize = CGSizeMake(250, 250);
        self.scrollDirection = UICollectionViewScrollDirectionVertical;
        self.sectionInset = UIEdgeInsetsMake(100, 0.0, 100, 0.0);
        self.minimumLineSpacing = 50.0;
    return self;
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)oldBounds {
    return YES;
-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect {
    NSArray* array = [super layoutAttributesForElementsInRect:rect];
    CGRect visibleRect;
    visibleRect.origin = self.collectionView.contentOffset;
    visibleRect.size = self.collectionView.bounds.size;
    return array;
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {
    CGFloat offsetAdjustment = MAXFLOAT;
    CGFloat horizontalCenter = proposedContentOffset.x + (CGRectGetWidth(self.collectionView.bounds) / 2.0);
    CGRect targetRect = CGRectMake(proposedContentOffset.x, 0.0, self.collectionView.bounds.size.width, self.collectionView.bounds.size.height);
    NSArray* array = [super layoutAttributesForElementsInRect:targetRect];
    for (UICollectionViewLayoutAttributes* layoutAttributes in array) {
        CGFloat itemHorizontalCenter = layoutAttributes.center.x;
        if (ABS(itemHorizontalCenter - horizontalCenter) < ABS(offsetAdjustment)) {
            offsetAdjustment = itemHorizontalCenter - horizontalCenter;
    return CGPointMake(proposedContentOffset.x + offsetAdjustment, proposedContentOffset.y);

Now lets import Cell.h and CollectionViewLayout.h in our ViewController class implementation, and put this into our viewDidLoad: in the same file:

[self.collectionView registerClass:[Cell class] forCellWithReuseIdentifier:@"MY_CELL"];

That was certainly a lot of code, let’s step through it. First, in the init method we set the itemSizescrollDirectionsectionInset and minimumLineSpacing. Secondly, implementing shouldInvalidateLayoutForBoundsChange: method instructs the layout to reload itself if the bounds change (such as an item getting bigger or smaller. In layoutAttributesForElementsInRect:, we setup an array of the visual objects, which contains their attributes. And finally, intargetContentOffsetForProposedContentOffset: we tell the view at what point to stop scrolling.

With the layout complete, make the following additions to the AppDelegate implementation to create a collection view controller that uses the layout created in the previous snippet and add it as the root view.

#import "AppDelegate.h"
#import "CollectionViewLayout.h"
#import "ViewController.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    CollectionViewLayout *collectionViewLayout = [[CollectionViewLayout alloc] init];
    self.viewController = [[ViewController alloc] initWithCollectionViewLayout:collectionViewLayout];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;

Now build the project and see what happens. If all works as expected, you will have 4 sections with 4 cells each, that are scrollable vertically similar to the screenshot below.

Now, to really drive-home the flexibility the UICollectionView class provides, make the following change to to the init method implementation of theCollectionViewLayout class.

self.scrollDirection = UICollectionViewScrollDirectionVertical;


self.scrollDirection = UICollectionViewScrollDirectionHorizontal;

Re-run the project and you should have horizontal scrolling. It really is that simple.

There is also a new function that you need to call if something in your layout changes. By calling [self invalidateLayout] you are telling the collection view that it needs to re-query the layout information. You would do this if you wanted to implement custom events such as resizing a cell with a touch, a gesture, or when another action is taken. This is similar to the reloadData method on UITableView.

With this new class, Apple has really given developers access to a very powerful new tool. You can use UICollectionView to integrate new and exciting layouts into our apps, resulting in a much better experience for your users.

I have also attached the sample project that we walked through in this post, feel free to download and poke around.

If anyone has questions, I can be reached at: pdakessian@captechconsulting.com.