Thursday Tech Tip – Custom UICollectionViews

7 Feb , 2014 Technology,Thursday Tech Tips

Thursday Tech Tip – Custom UICollectionViews

Custom UICollectionView ExampleI dealt with a frustrating Xcode 5 situation earlier this week. I was trying to add a custom UICollectionView at the bottom of a standard UIView but was running into serious memory leaks. The app I was working on kept crashing and freezing up and what’s worse is that I was not getting any Xcode specific errors. I had a feeling that it had something to do with the UICollectionView I had added and was populating with data from a REST call. I was hoping to recreate the effect you see to the right here in the Flipboard app.

I placed break points all up and down the code and everything seemed to be firing correctly but the app remained non-responsive and leaking memory like crazy. So, I decided to remove all traces of the UICollectionView I had added and decided to start from scratch and see if I could find out what was wrong. The key issue I realized was that I was instantiating an unlimited number of versions of the UICollectionView by declaring the view I was adding it to as a delegate and data source in the actual code as well as adding these same connections in Xcode Storyboard builder.

The long and short of it is, only connect your custom UICollectionView in the Storyboard to the ViewController you are adding it to in order to avoid memory and version issues. So, here is a simple flow below on what you should do if you want to add a custom UICollectionView.

Add UICollectionView to your standard view controller in Xcode StoryBoard. Good.

UICollectionView Storyboard Placement

UICollectionView Storyboard Placement

Control Drag connection from UICollectionView to your View Controller. Good.

UICollectionView Storyboard Connections

UICollectionView Storyboard Connections

Confirm Connections in Xcode Connections Inspector. Good.

UICollectionView XCode Connections

UICollectionView XCode Connections

Add code for numberOfItemsInSection and cellForItemAtIndexPath methods in your implementation file. Good.

#pragma mark - Custom Collection View

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return myObjects.count;
}

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

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

    Object* newObject = [myObjects objectAtIndex:indexPath.row];

    UIImageView *objectImage = (UIImageView *)[cell viewWithTag:101];
    NSData* imageData = [[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:newObject.url]];
    objectImage.image = [UIImage imageWithData:imageData];

    UILabel *objectLabel = (UILabel *)[cell viewWithTag:102];
    objectLabel.text = newObject.name;

    return cell;
}

Add code for Delegate and DataSource in your view header file. BAD.

@interface MyViewController : UIViewController <uicollectionviewdelegate, uicollectionviewdatasource="">

There you go, now go try this at home.

, , ,


Leave a Reply