以编程方式使用数据源创建 NSCollectionView
Creating NSCollectionView with datasource programmatically
我正在尝试使用 NSCollectionViewDataSource
以编程方式创建 NSCollectionView
。
代码很简单:
self.collectionView = [[NSCollectionView alloc] init];
// Add collection view to self.view etc.
self.collectionView.dataSource = self;
[self.collectionView registerClass:[NSCollectionViewItem class] forItemWithIdentifier:@"test"]
self.collectionView.collectionViewLayout = gridLayout;
[self.collectionView reloadData]
这会导致调用以下方法(如果我没有明确设置 collectionViewLayout
属性,这两个方法也不会被调用):
- (NSInteger)numberOfSectionsInCollectionView:(NSCollectionView*)collectionView
- (NSInteger)collectionView:(NSCollectionView*)collectionView numberOfItemsInSection:(NSInteger)section
但是,collectionView:itemForRepresentedObjectAtIndexPath:
从未被调用过。为了确保最后一个数据源方法被调用,我还需要做些什么吗?我已经确保这两个计数调用 return > 0,所以这不是问题。
看来问题实际上是我没有将 NSCollectionView 包装在 NSScrollView 中。如果它没有包含在滚动视图中,这可能与布局不正确有关(因此不会从数据源请求项目)。
过去几天我一直在研究不同的场景,我敢说使用或不使用 NSScrollView 实际上没有什么区别。无论有没有 scrollView,我都遇到了同样的错误和限制。
"old school" 和新奇的 collectionView 之间的选择确实有很大的不同。 "old school" 我的意思是设置 itemPrototype 和 contents 属性,像这样:
NSCollectionView *collectionView = [[NSCollectionView alloc] init];
collectionView.itemPrototype = [TBCollectionViewItem new];
collectionView.content = self.collectionItems;
NSInteger index = 0;
for (NSString *title in _collectionItems) {
NSIndexPath *path = [NSIndexPath indexPathForItem:index inSection:0];
TBCollectionViewItem *item = [collectionView makeItemWithIdentifier:@"Test" forIndexPath:path];
item.representedObject = title;
index++;
}
// Plays well with constraints
新学校,大概是这样的:
NSCollectionView *collectionView = [[NSCollectionView alloc] init];
collectionView.identifier = TBCollectionViewIdentifier;
[collectionView registerClass:[TBCollectionViewItem class] forItemWithIdentifier:TBCollectionViewItemIdentifier]; //register before makeItemWithIdentifier:forIndexPath: is called.
TBCollectionViewGridLayout *gridLayout = [TBCollectionViewGridLayout collectionViewGridLayout:NSMakeSize(250, 100)]; //getting the contentSize from the scrollView does not help
collectionView.collectionViewLayout = gridLayout;
collectionView.dataSource = self;
现在,您可能已经注意到 registerClass: 必须在 makeItemWithIdentifier:forIndexPath 之前调用的注释。实际上,这意味着在设置 .dataSource 之前调用 registerClass:,而在您的代码中您首先设置 .dataSource。文档状态:
Although you can register new items at any time, you must not call the makeItemWithIdentifier:forIndexPath: method until after you register the corresponding item.
我希望我可以说通过切换这两行,所有布局问题都将得到解决。不幸的是,我发现 .collectionViewLayout / .dataSource 组合会导致(自动)布局灾难。是否可以通过从 NSCollectionViewGridLayout 切换到 flowLayout 来解决这个问题,我还不确定。
我正在尝试使用 NSCollectionViewDataSource
以编程方式创建 NSCollectionView
。
代码很简单:
self.collectionView = [[NSCollectionView alloc] init];
// Add collection view to self.view etc.
self.collectionView.dataSource = self;
[self.collectionView registerClass:[NSCollectionViewItem class] forItemWithIdentifier:@"test"]
self.collectionView.collectionViewLayout = gridLayout;
[self.collectionView reloadData]
这会导致调用以下方法(如果我没有明确设置 collectionViewLayout
属性,这两个方法也不会被调用):
- (NSInteger)numberOfSectionsInCollectionView:(NSCollectionView*)collectionView
- (NSInteger)collectionView:(NSCollectionView*)collectionView numberOfItemsInSection:(NSInteger)section
但是,collectionView:itemForRepresentedObjectAtIndexPath:
从未被调用过。为了确保最后一个数据源方法被调用,我还需要做些什么吗?我已经确保这两个计数调用 return > 0,所以这不是问题。
看来问题实际上是我没有将 NSCollectionView 包装在 NSScrollView 中。如果它没有包含在滚动视图中,这可能与布局不正确有关(因此不会从数据源请求项目)。
过去几天我一直在研究不同的场景,我敢说使用或不使用 NSScrollView 实际上没有什么区别。无论有没有 scrollView,我都遇到了同样的错误和限制。
"old school" 和新奇的 collectionView 之间的选择确实有很大的不同。 "old school" 我的意思是设置 itemPrototype 和 contents 属性,像这样:
NSCollectionView *collectionView = [[NSCollectionView alloc] init];
collectionView.itemPrototype = [TBCollectionViewItem new];
collectionView.content = self.collectionItems;
NSInteger index = 0;
for (NSString *title in _collectionItems) {
NSIndexPath *path = [NSIndexPath indexPathForItem:index inSection:0];
TBCollectionViewItem *item = [collectionView makeItemWithIdentifier:@"Test" forIndexPath:path];
item.representedObject = title;
index++;
}
// Plays well with constraints
新学校,大概是这样的:
NSCollectionView *collectionView = [[NSCollectionView alloc] init];
collectionView.identifier = TBCollectionViewIdentifier;
[collectionView registerClass:[TBCollectionViewItem class] forItemWithIdentifier:TBCollectionViewItemIdentifier]; //register before makeItemWithIdentifier:forIndexPath: is called.
TBCollectionViewGridLayout *gridLayout = [TBCollectionViewGridLayout collectionViewGridLayout:NSMakeSize(250, 100)]; //getting the contentSize from the scrollView does not help
collectionView.collectionViewLayout = gridLayout;
collectionView.dataSource = self;
现在,您可能已经注意到 registerClass: 必须在 makeItemWithIdentifier:forIndexPath 之前调用的注释。实际上,这意味着在设置 .dataSource 之前调用 registerClass:,而在您的代码中您首先设置 .dataSource。文档状态:
Although you can register new items at any time, you must not call the makeItemWithIdentifier:forIndexPath: method until after you register the corresponding item.
我希望我可以说通过切换这两行,所有布局问题都将得到解决。不幸的是,我发现 .collectionViewLayout / .dataSource 组合会导致(自动)布局灾难。是否可以通过从 NSCollectionViewGridLayout 切换到 flowLayout 来解决这个问题,我还不确定。