Objective c 以编程方式使用数据源创建NSCollectionView

Objective c 以编程方式使用数据源创建NSCollectionView,objective-c,macos,cocoa,nscollectionview,Objective C,Macos,Cocoa,Nscollectionview,我正在尝试使用NSCollectionViewDataSource以编程方式创建一个NSCollectionView 代码非常简单: self.collectionView = [[NSCollectionView alloc] init]; // Add collection view to self.view etc. self.collectionView.dataSource = self; [self.collectionView registerClass:[NSCollectio

我正在尝试使用
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
属性,这两个方法也不会被调用):


但是,
collectionView:itemforRepresentedObjectIndexPath:
从未被调用。为了确保调用最后一个数据源方法,是否还需要执行其他操作?我已确保两次计数调用返回>0,因此这不是问题。

因此,问题似乎实际上是我没有将NSCollectionView包装到NSScrollView中。如果布局没有包装在滚动视图中,这可能与布局不正确有关(因此没有从数据源请求项目)

在过去的几天里,我一直在研究不同的场景,我敢说,使用或不使用NSScrollView实际上没有什么区别。无论是否使用scrollView,我都会遇到同样的错误和限制

真正造成巨大差异的是在“旧式”和新型collectionView之间的选择。“old school”是指设置itemPrototype和Content属性,如下所示:

    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。文件规定:

尽管可以随时注册新项,但在注册相应项之前,不能调用makeItemWithIdentifier:forIndexPath:方法


我希望我可以说,通过切换这两条线路,所有布局问题都将得到解决。不幸的是,我发现.collectionViewLayout/.dataSource组合会导致(自动)布局灾难。从NSCollectionViewGridLayout切换到flowLayout是否可以解决这个问题,我还不确定。

尝试从gridLayout切换到新的gridLayout(我忘了它叫什么)。网格布局是旧样式的布局。
NSCollectionViewGridLayout
在10.11中提供了新的数据源方法,因此它应该可以工作。尝试将其更改为
NSCollectionViewFlowLayout
,但不幸的是,它仍然没有调用
项ForRepresentedObjectIndexPath
。在设置数据源后注册nib是我修复它的方法。谢谢
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;