Search code examples
ios6xcode4.5uicollectionview

UICollectionView Setup Help for Newbie


First, apologies if the answer is quite obvious but I'm brand new to iOS development (like this is the first app I'm trying to program even though it's just for me to play with :P) so the probability that my problem is rather minor is quite high.

Code (zip file containing the xcode project):

http://www.mediafire.com/?p55xw0q2dwwwwvm

I promise there's nothing else in there that's harmful :).

Problem:

I'm following:

http://www.techotopia.com/index.php/An_iPhone_iOS_6_Storyboard-based_Collection_View_Tutorial

I'm attempting to make a UICollectionView to play around with. I got down to the "Testing the Application" section. I put my own spin on a few parts from the guide:

  1. instead of using different pictures, I just use 1 picture with a label at the bottom that just has a number in it. The number is dynamically set. Yes, I could implement it without the array I'm using, but having that array there will be helpful if I extend this project's scope in the future.

  2. I added code in viewDidLoad to set the view layout to a flow layout. This was done again for futureproofing since once I get this working at a basic form I want to play around with formatting which will require me to subclass flowlayout.

The code compiles without errors but nothing shows up on the screen. I've checked the code to the best of my ability for about an hour or two, but nothing I did made any difference. My controller class is a bare bones attempt to just get the collection view to show up on screen, and my cell class is a bare bones cell with just an imageview and label in it.

Thanks for any help that can be given to get this working!

tl;dr Just look at the bolded stuff. Code provided below for convenience:

MyCollectionViewController.m

#import "MyCollectionViewController.h"

    @interface MyCollectionViewController ()
    @property (nonatomic, strong) NSMutableArray *dataArray;
    @end

    @implementation MyCollectionViewController

    @synthesize dataArray = _dataArray;

    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            // Custom initialization
        }
        return self;
    }

    - (void)viewDidLoad
    {
        [super viewDidLoad];

        // Create data to display
        for(int i = 0; i < 50; i++){
            [self.dataArray addObject:[NSString stringWithFormat:@"%d", i]];
        }

        // Configure Layout
        UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
        [flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
        [self.collectionView setCollectionViewLayout:flowLayout];

    }

    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }

    #pragma mark -
    #pragma mark UICollectionViewDataSource

    -(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
    {
        return 1;
    }

    -(NSInteger)collectionView:(UICollectionView*)collectionView numberOfItemsInSection:(NSInteger)section
    {
        return [self.dataArray count];
    }

    -(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        MyCollectionViewCell *myCell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MyCell" forIndexPath:indexPath];
        int row = [indexPath row];
        UIImage* image = [UIImage imageNamed:@"200px-AND_ANSI"];
        myCell.cellTitle = [self.dataArray objectAtIndex:row];
        myCell.cellImageView.image = image;
        myCell.backgroundColor = UIColor.whiteColor;

        return myCell;
    }

MyCollectionViewcontroller.h

#import <UIKit/UIKit.h>
#import "MyCollectionViewCell.h"

@interface MyCollectionViewController : UICollectionViewController <UICollectionViewDataSource, UICollectionViewDelegate>

@end

MyCollectionViewCell.h

#import <UIKit/UIKit.h>

@interface MyCollectionViewCell : UICollectionViewCell
@property (strong, nonatomic) IBOutlet UIImageView *cellImageView;
@property (strong, nonatomic) IBOutlet UILabel *cellTitle;

@end

MyCollectionViewCell.m

#import "MyCollectionViewCell.h"

@implementation MyCollectionViewCell

@synthesize cellImageView = _cellimageView;
@synthesize cellTitle = _cellTitle;

- (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
}
*/

@end

Solution

  • self.dataArray is nowhere allocated/initialized in your code and therefore is equal to nil. Sending messages to nil is allowed, but has no effect, therefore even after

    for(int i = 0; i < 50; i++){
        [self.dataArray addObject:[NSString stringWithFormat:@"%d", i]];
    }
    

    self.dataArray is still nil, and [self.dataArray count] returns 0.

    You have to allocate and initialize the array with

    self.dataArray = [[NSMutableArray alloc] init];
    

    A proper place is some initXXX method of the view controller. But initWithNibName: is not called if the view controller is instantiated from a storyboard file, you have to use initWithCoder: instead:

    - (id)initWithCoder:(NSCoder *)coder
    {
        self = [super initWithCoder:coder];
        if (self) {
            self.dataArray = [NSMutableArray array];
        }
        return self;
    }