I have a particular UICollectionViewCell
that I want to instantiate myself, and add to a UICollectionView
. In order for this to work, the UICollectionViewCell
instance needs its .reuseIdentifier
property to be set.
Normally, the class or Nib that describes the cell is registered with the collection view, and the collection view instantiates the cell with its .reuseIdentifier
already set, with these methods:
- registerClass:forCellWithReuseIdentifier:
- registerNib:forCellWithReuseIdentifier:
However, since I am constructing this cell outside of the collection view, these do not apply.
When I create the cell myself, there appears to be no way to set its .reuseIdentifier
(because it is a readonly property, and there are no init...
methods that initialize it).
When .reuseIdentifier
is not set, the UICollectionView
throws an exception when the cell is added. This behavior is different from UITableView
, where reuse identifiers were optional.
An easy workaround to set the collection view cell's reuse identifier is to embed it in a .xib
file and use the Identifier
box, then create an instance of the cell with
[NSBundle.mainBundle loadNibNamed:@"MyCellName" owner:self options:nil][0];
I can then pass the above-instantiated UICollectionViewCell
and everything works fine.
...but that seems like a pretty silly and arbitrary hoop to jump through. Is there some other way to get this property set on the cell instance without the .xib
-wrapper detour?
Update: Apple's documentation says this:
To simplify the creation process for your code, the collection view requires that you always dequeue views, rather than create them explicitly in your code.
...which is actually not true, because it doesn't require this (i.e., externally-instanced cells work fine as long as their identifier is set somehow, e.g. if loaded from a .xib
), and it also doesn't "simplify the creation process for my code" in my particular use case (rather requires an extra file; further it would be messy to require that the collection view create these few complex one-offs).
But the above does seem to imply that the answer to the question is no: it's intentionally "difficult" to create a usable cell except by having the collection view dequeue it.
I'm sorry to say it, but I think you're going to have to accept the fact that UICollectionView is the sole Apple-branded factory for producing UICollectionViewCells. So if you have two collection views in which you want to display the exact same object, you're out of luck!
The good news is that if you have two collection view in which you want to display a cell that looks exactly the same as in the other, then you can accomplish your task. It's easy:
@interface MyModelClass : NSObject
// a bunch of data
@end
@interface MyCollectionViewCell : UICollectionViewCell
-(void)refreshCellWithObject:(MyModelClass *)object;
@end
Meanwhile, in whichever classes own the UICollectionView cv1 and cv2
[[self cv1] registerClass:[MyCollectionViewCell class] forCellWithReuseIdentifier:@"MyCollectionViewCell"];
and
[[self cv2] registerClass:[MyCollectionViewCell class] forCellWithReuseIdentifier:@"MyCollectionViewCell"];
And their data sources can look the same
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MyModelObject *obj = [self theObjectIWant];
MyCollectionViewCell *cell;
cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MyCollectionViewCell" forIndexPath:indexPath];
[cell refreshCellWithObject:obj];
return cell;
}