如何在不对其进行子类化的情况下使用 NSCollectionViewItem?
How to use NSCollectionViewItem without subclassing it?
我正在编写一个非常简单的 macOS 应用程序,我想在集合视图中显示一些图像。对于它们的显示方式,我不需要任何特殊行为。 docs for NSCollectionViewItem 说:
The default implementation of this class supports the creation of a simple item that displays a single image or string.
这就是我想要的。但是,我找不到有关如何创建默认 NSCollectionViewItem
的任何信息。
documentation for NSCollectionView 状态:
Every data source object is required to implement the following methods:
collectionView:numberOfItemsInSection:
collectionView:itemForRepresentedObjectAtIndexPath:
上面的第二种方法 returns NSCollectionViewItem
。通过阅读示例,我了解到在这种情况下创建 NSCollectionViewItem
的传统方法是调用:
NSCollectionViewItem* newCollectionViewItem = [imageCollectionView makeItemWithIdentifier:<some identifier>
forIndexPath:indexPath];
问题是我不明白 <some identifier>
应该是什么。我没有包含 NSCollectionViewItem
的笔尖,因为我没有对它进行子类化或以任何方式对其进行自定义。我已尝试将以下内容添加到我的数据源中:
- (void)awakeFromNib
{
[imageCollectionView registerClass:[NSCollectionViewItem class]
forItemWithIdentifier:@"Image"];
}
其中 imageCollectionView
是有问题的 NSCollectionView
。然后在我的 - (NSCollectionViewItem *)collectionView:itemForRepresentedObjectAtIndexPath:
方法中,我调用:
NSCollectionViewItem* newCollectionViewItem = [imageCollectionView makeItemWithIdentifier:@"Image"
forIndexPath:indexPath];
但这会引发异常并将其打印到控制台:
2016-12-19 17:51:27.463 MyApp[28177:3926764] -[NSNib _initWithNibNamed:bundle:options:] could not load the nibName: NSCollectionViewItem in bundle (null).
后跟堆栈跟踪。
那么我该如何创建和使用未以任何方式子类化或修改的 NSCollectionViewItem
?
这是一个非常简单的示例,它使用 Nib 作为项目的原型:
@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
NIB 只包含一个 NSCollectionViewItem
和一个文本字段作为视图。
附录:
我认为您应该为 registerClass 变体创建一个 NSCollectionViewItem.xib
。如果您没有在 loadView
中手动创建其视图,视图控制器将搜索名称为 class 的 NIB。因此,您不能使用没有 NIB 的普通 NSCollectionViewItem
来注册 class,因为 makeItemWithIdentifier:forIndexPath:
将访问该项目的视图。
我找到了一种无需添加 .xib
文件即可设置 NSCollectionView
的方法。
诀窍是继承自 NSCollectionViewItem
并将该子类用于 -[NSCollectionView registerClass:forItemWithIdentifier:]
。
#import "ViewController.h"
@interface MyViewItem : NSCollectionViewItem
@end
@implementation MyViewItem {
}
- (instancetype)initWithNibName:(NSNibName)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nil bundle:nil];
NSButton *button = [[NSButton alloc] initWithFrame:NSZeroRect];
[button setTitle:@"Button"];
[self setView:button];
return self;
}
@end
@implementation ViewController {
IBOutlet NSCollectionView *_collectionView;
}
- (void)viewDidLoad {
[super viewDidLoad];
[_collectionView registerClass:[MyViewItem class]
forItemWithIdentifier:@"item"];
[_collectionView setDataSource:self];
}
- (NSInteger)collectionView:(NSCollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 10;
}
- (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath {
return [_collectionView makeItemWithIdentifier:@"item" forIndexPath:indexPath];
}
@end
我正在编写一个非常简单的 macOS 应用程序,我想在集合视图中显示一些图像。对于它们的显示方式,我不需要任何特殊行为。 docs for NSCollectionViewItem 说:
The default implementation of this class supports the creation of a simple item that displays a single image or string.
这就是我想要的。但是,我找不到有关如何创建默认 NSCollectionViewItem
的任何信息。
documentation for NSCollectionView 状态:
Every data source object is required to implement the following methods:
collectionView:numberOfItemsInSection:
collectionView:itemForRepresentedObjectAtIndexPath:
上面的第二种方法 returns NSCollectionViewItem
。通过阅读示例,我了解到在这种情况下创建 NSCollectionViewItem
的传统方法是调用:
NSCollectionViewItem* newCollectionViewItem = [imageCollectionView makeItemWithIdentifier:<some identifier>
forIndexPath:indexPath];
问题是我不明白 <some identifier>
应该是什么。我没有包含 NSCollectionViewItem
的笔尖,因为我没有对它进行子类化或以任何方式对其进行自定义。我已尝试将以下内容添加到我的数据源中:
- (void)awakeFromNib
{
[imageCollectionView registerClass:[NSCollectionViewItem class]
forItemWithIdentifier:@"Image"];
}
其中 imageCollectionView
是有问题的 NSCollectionView
。然后在我的 - (NSCollectionViewItem *)collectionView:itemForRepresentedObjectAtIndexPath:
方法中,我调用:
NSCollectionViewItem* newCollectionViewItem = [imageCollectionView makeItemWithIdentifier:@"Image"
forIndexPath:indexPath];
但这会引发异常并将其打印到控制台:
2016-12-19 17:51:27.463 MyApp[28177:3926764] -[NSNib _initWithNibNamed:bundle:options:] could not load the nibName: NSCollectionViewItem in bundle (null).
后跟堆栈跟踪。
那么我该如何创建和使用未以任何方式子类化或修改的 NSCollectionViewItem
?
这是一个非常简单的示例,它使用 Nib 作为项目的原型:
@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
NIB 只包含一个 NSCollectionViewItem
和一个文本字段作为视图。
附录:
我认为您应该为 registerClass 变体创建一个 NSCollectionViewItem.xib
。如果您没有在 loadView
中手动创建其视图,视图控制器将搜索名称为 class 的 NIB。因此,您不能使用没有 NIB 的普通 NSCollectionViewItem
来注册 class,因为 makeItemWithIdentifier:forIndexPath:
将访问该项目的视图。
我找到了一种无需添加 .xib
文件即可设置 NSCollectionView
的方法。
诀窍是继承自 NSCollectionViewItem
并将该子类用于 -[NSCollectionView registerClass:forItemWithIdentifier:]
。
#import "ViewController.h"
@interface MyViewItem : NSCollectionViewItem
@end
@implementation MyViewItem {
}
- (instancetype)initWithNibName:(NSNibName)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nil bundle:nil];
NSButton *button = [[NSButton alloc] initWithFrame:NSZeroRect];
[button setTitle:@"Button"];
[self setView:button];
return self;
}
@end
@implementation ViewController {
IBOutlet NSCollectionView *_collectionView;
}
- (void)viewDidLoad {
[super viewDidLoad];
[_collectionView registerClass:[MyViewItem class]
forItemWithIdentifier:@"item"];
[_collectionView setDataSource:self];
}
- (NSInteger)collectionView:(NSCollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 10;
}
- (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath {
return [_collectionView makeItemWithIdentifier:@"item" forIndexPath:indexPath];
}
@end