Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

Adding a title like a username to a collectionViewCell that also displays an image

Hi,

I've worked through the photo bombers app and i'm just thinking of how i would go about adding a username to a collectionviewcell that also holds an image.

Basically like Instagram has a users username above the image.

Any help would be fantastic, thanks!

5 Answers

I am currently working on an app that uses a collection view and the thing I like to do in such a situation is split out the CollectionViewCell into a class of its own. This way you have somewhat of a template for your CollectionViewCells that can be customized without being limited to what is available in the storyboard editor (interface builder). Here is somewhat of a prototype of how I do this:

First, I make a new class for the CollectionViewCells:

ExampleCell.h

#import <UIKit/UIKit.h>

@interface ExampleCell : UICollectionViewCell

@property (nonatomic, strong) IBOutlet UILabel *userNameLabel;
//Add any properties you would like to include in the cell
//Also connect these properties to UI objects on the prototype cell

@end

ExampleCell.m

#import "ExampleCell.h"

@implementation ExampleCell

//This is default init code. Add anything here you would like to be run during initialization of the cell.
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
    //Add any drawing code you need here. For example, I placed a method here that loads the font of a label in the cell
}

@end

UICollectionViewDataSource Methods (called inside of a view controller as part of the CollectionViewDataSourceDelegate)

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

    ExampleCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ExampleCell" forIndexPath:indexPath];
//Make sure to click on your prototype cell in the storyboard and set "ReuseIdentifier" to the same value in the line above

//Fill your CollectionView with cells constructed from an array (or another data type)
    for (int i = 0; i < arrayCount; i++) {
        if (indexPath.row == i) {
            NSString *userName = [array objectAtIndex:indexPath.row];
            cell.userNameLabel.text = userName;
        }
    }
    return cell;
}

This is just a basic example of how you can customize your cells by making separate classes for them. If you do this, the sky is the limit as far as what each cell can contain.

Add a label to the collection cell and parse the Instagram information to include the user name.

thanks, i also had another issue, in interface builder i set up a tabBarController which is my root view controller. However, i am following the photo bombers tutorial code where I change the init method to set up my collection view in one of my tabs and it sets this to the rootviewcontroller resetting all my work in interface builder. is there a way of initialising the collectionviewcontroller without setting it as my root view controller?

Did you drag out the full "CollectionViewController" from the object library into your storyboard? What you can do instead is find the CollectionView object in the object library and place it inside a different view controller. This way you can initialize the CollectionView inside that ViewController however/whenever you like.

Hayden Evans any idea why this code won't work? trying to initialise my collectionView object:

#import "JRViewController.h"
#import "PhotoCell.h"
#import <Parse/Parse.h>

@interface JRViewController ()

@end

@implementation JRViewController


- (void)viewDidLoad
{
    [super viewDidLoad];
   [self performSegueWithIdentifier:@"Segue1" sender:self];

    UICollectionView *collectionView = [[UICollectionView alloc]init];


    collectionView.backgroundColor = [UIColor whiteColor];

    [collectionView registerClass:[PhotoCell class] forCellWithReuseIdentifier:@"photo"];

    [self setup];



}


-(NSInteger) collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return 10;
}

- (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"photo";

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


    cell.backgroundColor = [UIColor lightGrayColor];

    return cell;
}

-(void) setup {


    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];



    layout.itemSize = CGSizeMake(306.0, 306.0);
    layout.minimumInteritemSpacing = 150.0;
    layout.minimumLineSpacing = 50.0;



    self.collectionView.collectionViewLayout = layout;
}



@end

At first glance, it appears that you haven't registered your CollectionViewDelegate or CollectionViewDataSource with the ViewController you are showing above. To do this, make sure you go into your header and use the following code:

ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UICollectionViewDataSource, UICollectionViewDelegate>

@end

After doing that make sure to set the delegate and dataSource to self inside the ViewController in which you call the delegate/dataSource methods. Like this:

ViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.collectionView.delegate = self; //Make sure to set these in the future!
    self.collectionView.dataSource = self;
...

I'm not sure if this will solve your exact issue but I do know that if you do not set these delegate and dataSource objects as I have indicated above, your corresponding delegate and dataSource methods will not be called during the construction of your CollectionView. It also looks like you are constructing it purely in code. In my case I used Storyboards, so a lot of the other code you have written above may be taken care of through Storyboards in my particular case.

Thanks for the help, eventually got it working. I'm also trying to implement a header in my collection View.

#import "ProfileViewController.h"
#import "PhotoCell.h"
#import <Parse/Parse.h>
#import "headerView.h"


@interface ProfileViewController ()

@end

@implementation ProfileViewController


- (void)viewDidLoad
{
    [super viewDidLoad];



    self.edgesForExtendedLayout = UIRectEdgeNone;

    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc]init];

    [layout setItemSize:CGSizeMake(306.0, 306.0)];
    [layout setMinimumInteritemSpacing:150.0];
    [layout setMinimumLineSpacing:50.0];



    UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:self.view.frame collectionViewLayout:layout];
    [collectionView setDataSource:self];
    [collectionView setDelegate:self];

    [collectionView registerClass:[PhotoCell class] forCellWithReuseIdentifier:@"jack"];
    [collectionView registerClass:[headerView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header"];



    [self.view addSubview:collectionView];


    [collectionView setBackgroundColor:[UIColor whiteColor]];



}

-(NSInteger) collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return 10;
}

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


    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"jack" forIndexPath:indexPath];


    cell.backgroundColor = [UIColor lightGrayColor];

    return cell;
}

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    UICollectionReusableView *reusableview = nil;

    if (kind == UICollectionElementKindSectionHeader) {

        headerView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header" forIndexPath:indexPath];

    headerView.usernameLabel.text = @"hello";


        reusableview = headerView;
    }




    return reusableview;
}

@end

I've got the right method and set the data source as far as I can see but get the error saying 'UICollectionView dataSource is not set' any ideas?