21

I'm trying to add a UICollectionView to a .nib file in IB. I've worked through a few tutorials and had no problems.

In my existing app, when I drag a collection view into a view in IB and then expand the object, the CollectionView Flow Layout is there , but there is no collection view cell. I also cannot drag and drop a cell into the collection view. Also the collection view is displayed differently, showing an image of a grid of cells instead of the normal white box.

I've tried creating a new view controller with nib, and have the same results when adding a collectionView.

This app WAS targeting iOS 4.2, but I've changed the deployment target to iOS 6.

In any newly created projects I don't get this behavior.

Alpinista
  • 3,731
  • 5
  • 33
  • 45
  • 7
    OK, it seems that you can only layout a UICollectionView completely using IB inside a storyboard. In a .nib you get the behavior I described above. In a storyboard, you get the UICollectionViewCell with your UICollectionView. What's up with that??? – Alpinista Oct 08 '12 at 23:56
  • having this same issue as well, rather annoying – adit Oct 19 '12 at 21:57
  • Even in storyboard, you cannot drab and drop the collection view cell into a collection view object. Not sure why. – theiOSguy Aug 07 '13 at 17:20
  • i have this same issue. – Akbar Khan Feb 21 '19 at 05:16

4 Answers4

9

I can't tell you why it does not work, but for me the subclass approach from this blog post solved the problem:

http://www.adoptioncurve.net/archives/2012/09/a-simple-uicollectionview-tutorial.php

here is a short summary:

  • create a new class MyViewCell which extends UICollectionViewCell and create properties, actions, outlets and methods as needed.

@interface MyViewCell : UICollectionViewCell

  • create a View (xib file) with a Collection View Cell as its root object (and delete the object which is created by default).
  • in the attributes set the custom class of this Collection View Cell to your extended class MyViewCell (instead of the default UICollectionViewCell).
  • in the attributes under Collection Reusable View define an Identifier, e.g. myCell, you will need this later to register your call.
  • go back to your custom class and modify the inithWithFrame method to load and use your created view.

    - (id)initWithFrame:(CGRect)frame 
    { 
       self = [super initWithFrame:frame]; 
       if (self) 
       { 
         // Initialization code 
         NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"CVCell" owner:self options:nil];
    
         if ([arrayOfViews count] < 1) { return nil; }
    
         if (![[arrayOfViews objectAtIndex:0] isKindOfClass:[UICollectionViewCell class]]) { return nil; }
    
         self = [arrayOfViews objectAtIndex:0];
       }
       return self;
    }
    
  • then you can register this class to be used by the collectionView with

[self.collectionView registerClass:[MyViewCell class] forCellWithReuseIdentifier:@"myCell"];

DELUXEnized
  • 1,110
  • 14
  • 21
  • Whilst this may theoretically answer the question, [it would be preferable](http://meta.stackexchange.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. – Shawn Chin Dec 20 '12 at 11:14
  • I have added more details to the answer. – DELUXEnized Dec 20 '12 at 14:22
  • Awesome! Just don't forget to register collectionView: [self.collectionView registerClass:[MyViewCell class] forCellWithReuseIdentifier:@"myCell"]; – atulkhatri Jan 02 '14 at 13:11
8

It's been a while since the question has been asked but I faced the same issue lately.

Eventually, I found the answer here.

In short:

  • You cannot drag and drop a UICollectionViewCell into a UICollectionView if you are in a .xib file. This is only possible in a storyboard.

  • The workaround is to create a .xib file for your custom cell and to register the cell manually using:

    [self.collectionView registerClass:[CollectionViewCell class] forCellWithReuseIdentifier:CELL_ID];

Community
  • 1
  • 1
Performat
  • 763
  • 8
  • 12
  • This is still an issue on Xcode 8.2.1. I think we have to use the workaround forever. – Samuel Cai Mar 02 '17 at 03:02
  • For the workaround, I have to use registerNib, or else the dequeueReusableCell is just an empty view, without any information configured in xib. – Samuel Cai Mar 02 '17 at 03:14
3

Define your cell view in a separate nib file. The view must be of type UICollectionViewCell or a subclass.

Then, you must register the nib with your collection view:

- (void)viewDidLoad
{
    UINib *cellNib = [UINib nibWithNibName:@"MyNib" bundle:nil];
    [self.collectionView registerNib:cellNib forCellWithReuseIdentifier:@"cell"];
}
hpique
  • 112,774
  • 126
  • 328
  • 461
  • 2
    for some reason this does not work. when dequeueing the cell, an exception is thrown: "nib must contain exactly one top level object which must be a UICollectionReusableView instance". this is really strange, since the documentation states "The nib file must contain only one top-level object and that object must be of the type UICollectionViewCell". – DELUXEnized Dec 19 '12 at 16:50
  • UICollectionViewCell inherits from UICollectionReusableView. – Michael Hogenson Feb 25 '14 at 01:28
0

While these answers are correct, the underlying cause of the problem is quite subtle and Apple needs to update their error message in the log. When you see:

Unknown class MyViewCell in Interface Builder file.

What it actually means is that your source code is missing the @implementation declaration or that the .m file has not been added to the target. So check your code and make sure you have:

@implementation MyViewCell

@end

This is true for both UITableViewCell and UICollectionViewCell.

I discuss the problem further at https://stackoverflow.com/a/12755891/539149 for the general case.

The interesting thing is that if you are missing the @implementation and call:

[self.myCollectionView registerClass:[MyViewCell class] forCellWithReuseIdentifier:@"MyViewCell"];

You will see:

Undefined symbols for architecture armv7:
  "_OBJC_CLASS_$_MyViewCell", referenced from:
      objc-class-ref in MyViewController.o
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)

So Apple knows about the problem, they just aren't detecting it during compilation. I would advise against putting custom cells in separate nibs or calling registerClass: forCellWithReuseIdentifier:. It's much cleaner to store the custom cell inside of its container UICollectionView or UITableView in Interface Builder.

Community
  • 1
  • 1
Zack Morris
  • 4,239
  • 2
  • 47
  • 78