【问题标题】:Creating NSCollectionView with datasource programmatically以编程方式使用数据源创建 NSCollectionView
【发布时间】:2019-01-16 12:23:44
【问题描述】:

我正在尝试使用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: 永远不会被调用。为了确保调用最后一个数据源方法,我还需要做些什么吗?我确保两个计数调用返回 > 0,所以这不是问题。

【问题讨论】:

  • 尝试从 gridLayout 更改为新的(我忘记它叫什么了)。网格布局是旧式布局。
  • NSCollectionViewGridLayout 在 10.11 中可以使用新的数据源方法,所以它应该可以工作。尝试将其更改为NSCollectionViewFlowLayout,但不幸的是它仍然没有调用itemForRepresentedObjectAtIndexPath

标签: objective-c macos cocoa nscollectionview


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    过去几天我一直在处理不同的场景,我敢说是否使用 NSScrollView 几乎没有区别。不管有没有scrollView,我都会遇到同样的错误和限制。

    真正产生巨大差异的是“老派”和新奇的 collectionView 之间的选择。 “老派”是指设置 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。文档状态:

    虽然你可以随时注册新的项目,但是在你注册了相应的项目之前,你不能调用makeItemWithIdentifier:forIndexPath:方法。

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

    【讨论】:

    • 在设置数据源后注册笔尖是为我解决的问题。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2013-02-05
    • 2018-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-24
    • 2016-08-30
    • 1970-01-01
    相关资源
    最近更新 更多