Skip to content

I 5.4. Providing Basic Content to a Collection View

rayastar edited this page Feb 15, 2015 · 2 revisions

Problem

You have already set up a flow layout for your collection view, but you don’t know how to render cells in your collection view.

Solution

Either use the UICollectionViewCell class directly to present your cells, or subclass this class and provide further implementation on top of that class. In addition, you can have a .xib file associated with your cell, as we will soon see.

Let’s take this one step at a time and start with the fastest and easiest way of creating our cells: instantiate objects of type UICollectionViewCell and feed them to our collection view in our data source. The UICollectionViewCell class has a content view property named contentView, where you can add your own views for display. You can also set various other properties of the cell, such as its background color, which is what we are going to do in this example. But before we begin, let’s first set the expectations of what we are going to achieve in this example code and explain the requirements.

So let’s get started. In your collection view controller, create a method that can return an array of three colors, which you will then assign to the cells for each section:

- (NSArray *) allSectionColors{

    static NSArray *allSectionColors = nil;

    if (allSectionColors == nil){
        allSectionColors = @[
                             [UIColor redColor],
                             [UIColor greenColor],
                             [UIColor blueColor],
                             ];
    }

    return allSectionColors;

}

After that, override the initWithCollectionViewLayout: designated initializer of your collection view controller and register the UICollectionViewCell with a specific iden‐ tifier. Don’t worry if this makes no sense yet, but look at it this way: for every cell that your collection view has to render, it will first look into a queue of reusable cells and find out if a reusable cell exists. If so, the collection view will pull the cell from the queue, and if not, it will create a new cell and return that to you for configuration.

In older versions of iOS, you had to manually create cells if the table view (collection views didn’t exist in older versions of iOS) could not find a reusable cell. However, with the introduction of newer APIs, what Apple has done with regard to reusable cells is very interesting indeed. It has exposed new APIs for both collection and table views so that you can register a call with the table or the collection view, and when you have to configure a new cell, you simply ask the table or the collection view to give you a new cell of that kind. If the cell exists in the reusable queue, it will be given to you. If not, the table or the collection view will automatically create that cell for you. This is called registering a reusable cell, and you can do it in two ways:

  • Register a cell using a class name.

  • Register a cell using a .xib file.

Both these ways of registering reusable cells are good and work perfectly with collection views. To register a new cell with a collection view using the cell’s class name, use the registerClass:forCellWithReuseIdentifier: method of the UICollectionView class, where the identifier is a simple string that you provide to the collection view. When you then attempt to retrieve reusable cells, you ask the collection view for the cell with a given identifier. To register a .xib file with the collection view you need to use the registerNib:forCellWithReuseIdentifier: instance method of your collection view. The identifier of this method also works, as explained earlier in this paragraph. The nib is an object of type UINib, which we will get to use later in this chapter.

- (instancetype) initWithCollectionViewLayout:(UICollectionViewLayout *)layout{

    self = [super initWithCollectionViewLayout:layout];
    if (self != nil){
        /* Register the cell with the collection view for easy retrieval */
        [self.collectionView registerClass:[UICollectionViewCell class]
                forCellWithReuseIdentifier:kCollectionViewCellIdentifier];
    }
    return self;

}

You can see that we are using the kCollectionViewCellIdentifier constant value as the identifier for our cells. We need to define this in our view controller:

#import "ViewController.h"

static NSString *kCollectionViewCellIdentifier = @"Cells";

@implementation ViewController

The default implementation of your collection view will have one section unless you implement the numberOfSectionsInCollectionView: method in your data source. We want three sections for our collection view, so let’s implement this method:

- (NSInteger)numberOfSectionsInCollectionView :(UICollectionView *)collectionView{
    return [self allSectionColors].count;
}

Part of the requirement for our application was for each cell to contain at least 20 and at most 40 cells. We can achieve this using the arc4random_uniform(x) function. It returns positive integers between 0 and x, where x is the parameter that you provide to this function. Therefore, to generate a number between 20 and 40, all we have to do is add 20 to the return value of this function while setting x to 20 as well. With this knowl‐ edge, let’s implement the collectionView:numberOfItemsInSection: method of our collection view’s data source:

- (NSInteger)collectionView:(UICollectionView *)collectionView
     numberOfItemsInSection:(NSInteger)section{
    /* Generate between 20 to 40 cells for each section */
    return 5 + arc4random_uniform(2);
}

Last but not least, we want to provide the cells to the collection view. For that we need to implement the collectionView:cellForItemAtIndexPath: method of our collection view’s data source:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
                  cellForItemAtIndexPath:(NSIndexPath *)indexPath{

    UICollectionViewCell *cell = [collectionView
     dequeueReusableCellWithReuseIdentifier:kCollectionViewCellIdentifier
     forIndexPath:indexPath];

    cell.backgroundColor = [self allSectionColors][indexPath.section];

    return cell;

}

As you can see, we are using the dequeueReusableCellWithReuseIdentifier:forIn dexPath: instance method of our collection view to pull reusable cells out of the queue. This method expects two parameters: the identifier of the cell that you have registered earlier with the collection view, and the index path at which that cell should be rendered. The index path is given to you in the same collectionView:cellForItemAtIndex Path: method as a parameter, so the only thing that you do have to provide is the identifier of the cell. The return value of this method will be a cell of type UICollectionViewCell, which you can configure. In this implementation, the only thing we have done is to set the background color of the cell to the background color that we had chosen earlier for all the cells in that section. One last thing to do before we wrap this up is to set the background color of our col‐ lection view to white to make it look a bit better than the default pitch-black color. So implement the viewDidLoad method of your collection view controller and set the background color of your collection view right there:

- (void) viewDidLoad{
    [super viewDidLoad];
    self.collectionView.backgroundColor = [UIColor whiteColor];
}
Clone this wiki locally