I am learning about NSCollectionView
compositional layout on macOS (12.4, Xcode 13.4). In the Swift version of this app everything works as expected, yet when converting it to Objective-C, while I get everything to compile, the app loads as blank.
I checked the outlets in the nib file (dataSource
and delegate
from Collection View to File's Owner), checked the creation of a reusable item (I build it through a custom nib). The error I get in the console when the app launches is as follows:
2022-07-21 15:26:25.817911+0200 Cocoa Pr L68 ObjC[14203:1414415] *** Assertion failure in -[_NSCollectionViewCore _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:], UICollectionView.m:6488
2022-07-21 15:26:25.818378+0200 Cocoa Pr L68 ObjC[14203:1414415] could not dequeue an item of kind: NSCollectionElementKindItem with identifier _NS:8 - must register a nib or a class for the identifier, or name a nib or class to match the identifier
Browsing the docs, I learned that NSCollectionView
doesn't have a dequeueReusable
kind of method like Table Views in iOS have so the first error is not clear to me. The second is even stranger because I've actually register a class for the identifier:
#import "CollectionViewController.h"
#import "CollectionViewItem.h"
@interface CollectionViewController ()
@property (weak) IBOutlet NSCollectionView *collectionView;
@end
@implementation CollectionViewController
@synthesize collectionView;
- (void)viewDidLoad {
[super viewDidLoad];
CollectionViewItem *collectionViewItem = [[CollectionViewItem alloc] init];
[collectionView registerClass:[NSCollectionViewItem class] forItemWithIdentifier:collectionViewItem.identifier];
[collectionView setCollectionViewLayout:self.listLayout];
}
The listLayout
method is defined afterwards in the same file. All NSCollectionViewDataSource
methods are properly defined as in the Swift version, for reference:
- (NSInteger)numberOfSectionsInCollectionView:(NSCollectionView *)collectionView {
return 3;
}
- (NSInteger)collectionView:(NSCollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 20;
}
- (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath {
NSCollectionViewItem *item = [collectionView makeItemWithIdentifier:collectionView.identifier forIndexPath:indexPath];
[item.textField setStringValue:[NSString stringWithFormat:@"%ld, %ld", indexPath.section, indexPath.item]];
return item;
}
The NSCollectionViewItem
class is thus defined:
#import "CollectionViewItem.h"
@implementation CollectionViewItem
- (instancetype)init
{
self = [super init];
if (self) {
self.identifier = @"CollectionViewItemReuseIdentifier";
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
@end
I wonder what piece of the puzzle is missing as these errors, while apparently clear, seem to point to something that I have implemented. Have I implemented it wrong? Or not completely?
I would be very grateful to anyone shedding some light on all this.
Thank you
The registered class should be CollectionViewItem
instead of NSCollectionViewItem
. Change
[collectionView registerClass:[NSCollectionViewItem class] forItemWithIdentifier:collectionViewItem.identifier];
to
[collectionView registerClass:[CollectionViewItem class] forItemWithIdentifier:collectionViewItem.identifier];
It's in the error could not load the nibName: NSCollectionViewItem
, but I'm so used to NS
that I didn't notice.