I am writing a very simple macOS application that I'd like to show a few images in a collection view. I don't need any special behavior for how they are displayed. The docs for NSCollectionViewItem say:
The default implementation of this class supports the creation of a simple item that displays a single image or string.
That is what I want. However, I can't find any information on how to create a default NSCollectionViewItem
.
The documentation for NSCollectionView states:
Every data source object is required to implement the following methods:
collectionView:numberOfItemsInSection:
collectionView:itemForRepresentedObjectAtIndexPath:
The second method above returns an NSCollectionViewItem
. From reading examples I gather that the traditional way of creating an NSCollectionViewItem
in this case is to call:
NSCollectionViewItem* newCollectionViewItem = [imageCollectionView makeItemWithIdentifier:<some identifier>
forIndexPath:indexPath];
The problem is that I don't understand what <some identifier>
should be. I don't have a nib that contains an NSCollectionViewItem
because I'm not subclassing it or customizing it in any way. I've tried adding the following to my data source:
- (void)awakeFromNib
{
[imageCollectionView registerClass:[NSCollectionViewItem class]
forItemWithIdentifier:@"Image"];
}
where imageCollectionView
is the NSCollectionView
in question. And then in my - (NSCollectionViewItem *)collectionView:itemForRepresentedObjectAtIndexPath:
method, I call:
NSCollectionViewItem* newCollectionViewItem = [imageCollectionView makeItemWithIdentifier:@"Image"
forIndexPath:indexPath];
But this throws an exception and prints this to the console:
2016-12-19 17:51:27.463 MyApp[28177:3926764] -[NSNib _initWithNibNamed:bundle:options:] could not load the nibName: NSCollectionViewItem in bundle (null).
followed by a stack trace.
So how do I go about creating and using an NSCollectionViewItem
that isn't subclassed or modified in any way?
Here is a very simple example which uses a Nib for the item's prototype:
@interface ViewController()
@property (weak) IBOutlet NSCollectionView *collectionView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSNib *theNib = [[NSNib alloc] initWithNibNamed:@"Item" bundle:nil];
[self.collectionView registerNib:theNib forItemWithIdentifier:@"item"];
}
#pragma mark NSCollectionViewDataSource
- (NSInteger)numberOfSectionsInCollectionView:(NSCollectionView *)inCollectionView {
return 1;
}
- (NSInteger)collectionView:(NSCollectionView *)inCollectionView numberOfItemsInSection:(NSInteger)inSection {
return 10;
}
- (NSCollectionViewItem *)collectionView:(NSCollectionView *)inCollectionView itemForRepresentedObjectAtIndexPath:(NSIndexPath *)inIndexPath {
NSCollectionViewItem *theItem = [inCollectionView makeItemWithIdentifier:@"item" forIndexPath:inIndexPath];
NSTextField *theLabel = (NSTextField *)theItem.view;
theLabel.stringValue = [NSString stringWithFormat:@"%d.%d", (int)inIndexPath.section, (int)inIndexPath.item];
return theItem;
}
@end
The NIB contains just a NSCollectionViewItem
with a text field as view.
Addendum:
I think you should create a NSCollectionViewItem.xib
for the registerClass variant. A view controller will search for a NIB with its class name, if you doesn't create its view manually in loadView
. Thus, you can't use plain NSCollectionViewItem
without a NIB for registering a class, because of makeItemWithIdentifier:forIndexPath:
will access the view of the item.