Skip to content

I 5.5. Feeding Custom Cells to Collection Views Using .xib Files

rayastar edited this page Feb 14, 2015 · 1 revision

Problem

You want to configure collection view cells in Interface Builder and feed those cells to your collection view for rendering.

Solution

Follow these steps:

  1. Create a subclass of the UICollectionViewCell and give it a name (we’ll use My CollectionViewCell for this example).

  2. Create an empty .xib file and name it MyCollectionViewCell.xib.

  3. Drop a Collection View Cell from the Objects Library in Interface Builder onto your empty .xib file (see Figure 5-7) and change the class name of the dropped object in Interface Builder to MyCollectionViewCell (see Figure 5-8). Because you make this association, when you load the .xib file programmatically, your custom class of MyCollectionViewCell will automatically be loaded into memory. This is pure magic!

  4. Customize your cell in Interface Builder. For every UI component that you drop on your cell, ensure that you create an associated IBOutlet either in the header or the implementation file of your class (MyCollectionViewCell).

  5. Register your nib with your collection view using the registerNib:forCellWithReuseIdentifier: instance method of your collection view. You can load your nib into memory using the nibWithNibName:bundle: class method of the UINib class, as we will see soon.

Now you have to associate our class with our .xib file. To do this, follow these steps:

  1. Open your MyCollectionViewCell.xib file in Interface Builder. In the Object Library, simply find the Collection View Cell (see Figure 5-7) and drop it into your .xib file. By default, this cell will be very small (50×50 points width and height) and will have a black background color.

  2. Explicitly select the cell on your .xib file by clicking on it. Open the Identity Inspector in Interface Builder and change the Class field’s value to MyCollection ViewCell, as shown earlier in Figure 5-8.

The next thing you need to do is add some UI components to your cell. Later, when you populate your collection view, we can change the value of those components. The best component for this demonstration would be an image view, so while you have your MyCollectionViewCell.xib file open in Interface Builder, drop an instance of UIImage View onto it. Connect that image view to the header file of your cell (the MyCollection ViewCell.h file) and name it imageViewBackgroundImage so that your cell’s header file will look like this:

#import <UIKit/UIKit.h>

@interface MyCollectionViewCell : UICollectionViewCell

@property (weak, nonatomic) IBOutlet UIImageView *imageViewBackgroundImage;

@end

The first modification that we have to make is to prepare a method in our app that can return a random image to us. We have an array of images, as explained before. So after instantiating the array, we need a handy little method that can grab a random image out of the array for us:

- (NSArray *) allImages{

    static NSArray *AllSectionImages = nil;

    if (AllSectionImages == nil){
        AllSectionImages = @[
                             [UIImage imageNamed:@"1"],
                             [UIImage imageNamed:@"2"],
                             [UIImage imageNamed:@"3"]
                             ];
    }

    return AllSectionImages;

}

- (UIImage *) randomImage{
    return [self allImages][arc4random_uniform([self allImages].count)];
}

Next, we need to override our collection view controller’s designated initializer to register our MyCollectionViewCell nib with our collection view:

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

    self = [super initWithCollectionViewLayout:layout];
    if (self != nil){
        /* Register the nib with the collection view for easy retrieval */
        UINib *nib = [UINib nibWithNibName:
                      NSStringFromClass([MyCollectionViewCell class])
                                    bundle:[NSBundle mainBundle]];

        [self.collectionView registerNib:nib
              forCellWithReuseIdentifier:kCollectionViewCellIdentifier];
    }
    return self;

}

Also, when asked how many sections we have, we will return a random number between 3 and 6. This is not really required—we could go with one section, but it won’t hurt to have more. Also for each section, we want to have between 10 and 15 cells:

- (NSInteger)numberOfSectionsInCollectionView
            :(UICollectionView *)collectionView{
    /* Between 3 to 6 sections */
    return 3 + arc4random_uniform(4);
}

- (NSInteger)collectionView:(UICollectionView *)collectionView
     numberOfItemsInSection:(NSInteger)section{
    /* Each section has between 10 to 15 cells */
    return 10 + arc4random_uniform(6);
}

Last but not least, we will ask the collection view for the cells and configure them with a random image:

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

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

    cell.imageViewBackgroundImage.image = [self randomImage];
    cell.imageViewBackgroundImage.contentMode = UIViewContentModeScaleAspectFit;

    return cell;

}
Clone this wiki locally