NSCollectionView 正在相互绘制 NSCollectionViewItems

NSCollectionView is drawing NSCollectionViewItems over each other

我的 NSCollectionView 正在相互绘制我的 NSCollection 项目。 更新:我添加了一个示例项目 GitHub Sample Project

更新:这已经有所改变 When the app first launches it looks like this

更新 我当前的示例有两个视图,它们当前位于自己的 nib 文件中,具有专用的 NScollectionViewItem 对象,它们目前在测试中是相同的。我基本上有一个 NSCollectionViewItem,它有一个带有 NSTextField 的子视图。具有所有约束条件。

对于集合视图,它被设置为网格控制器,理想情况下,我希望有 1 列。

为了用数据加载它,我制作了 ViewController NSCollectionViewDataSource,并实现了 - (NSInteger)collectionView:(NSCollectionView *)collectionView numberOfItemsInSection:(NSInteger)section- (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath

更新代码 包含完整代码:

- (void)viewDidLoad {
    [super viewDidLoad];

    // Do any additional setup after loading the view.

    [collectionView registerClass:ItemOne.class forItemWithIdentifier:@"Item1"];
    [collectionView registerClass:ItemTwo.class forItemWithIdentifier:@"Item2"];

    cellArray = [@[@"Item1", @"Item2", @"Item1", @"Item2", @"Item1"] mutableCopy];
}


- (void)setRepresentedObject:(id)representedObject {
    [super setRepresentedObject:representedObject];

    // Update the view, if already loaded.
}

#pragma mark - NSCollectionViewDatasource -
- (NSInteger)collectionView:(NSCollectionView *)collectionView
 numberOfItemsInSection:(NSInteger)section {

    // We are going to fake it a little.  Since there is only one section
    NSLog(@"Section: %ld, count: %ld", (long)section, [cellArray count]);

    return [cellArray count];
}

- (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView
 itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath {

    NSLog(@"IndexPath: %@, Requested one: %ld", indexPath, [indexPath item]);
    NSLog(@"Identifier: %@", [cellArray objectAtIndex:[indexPath item]]);

    NSCollectionViewItem *theItem = [collectionView makeItemWithIdentifier:[cellArray objectAtIndex:[indexPath item]] forIndexPath:indexPath];

    return theItem;
}

更新 ItemOne 和 ItemTwo 类 都是空的 类,每个的 nib 都有一个 NSCollectionViewItem,后者又有一个带有标签的视图。视图通过 NSCollectionViewItem 中的视图 属性 连接到 NSCollectionViewItem。目前没有约束,除了默认的

NSCollectionView网格设置如下:

Layout: Grid Dimensions: Max Rows: 0 Max Columns: 1 Min Item Size: Width: 250 Height: 150 Max Item Size: Width: 250 Height: 150

这是设置整个东西的代码,此时没有将它绑定到数据源。

看来无论我怎么改设置,甚至把CollectionView的类型改成Flow都没有改变,看起来都一样

我一直将此作为自动布局问题来处理,因为最初存在一些自动布局问题,但这些问题都已解决。

如有任何帮助,我们将不胜感激。

数据数组应该保存数据而不是 NSCollectionViewItems。在 collectionView:itemForRepresentedObjectAtIndexPath: 中你调用 makeItemWithIdentifier:forIndexPath:。致电 registerClass:forItemWithIdentifier:registerNib:forItemWithIdentifier: 注册您的 class 或笔尖。

NSCollectionView, collectionView:itemForRepresentedObjectAtIndexPath: and makeItemWithIdentifier:forIndexPath: 的文档中有更多信息。

编辑:

有两种方法可以提供NSCollectionViewItem

registerClass:forItemWithIdentifier:。当集合视图需要一个新项目时,它会实例化这个 class。 NSCollectionViewItemNSViewController 的子 class,NSViewController 查找与 class 同名的笔尖。 NSCollectionViewItem 是 nib 的所有者。

registerNib:forItemWithIdentifier:。当集合视图需要一个新项目时,它会加载这个 nib。 NSCollectionViewItem 是笔尖中的顶级对象。

您将 registerClass:forItemWithIdentifier: 与 xib 混合用于 registerNib:forItemWithIdentifier:。使用 registerNib:forItemWithIdentifier: 或修复 xib。

我想通了。

并且已经制作了一个 github 版本的回购 Working Version of Collection View Sample Application

第一件事。多亏了 Willeke 掌握了原始 xib 的设置方式,我才能够让 Grid 类型正常工作。但最后,如果你可以让它做你想做的事,那么 Grow 视图是一种更好的视图类型,因为它支持部分,以及视图之间的距离等。所以尽管我开始想要使用 Grid 类型,但我将要实现我应用中的成长类型。

所以我使用 Grow 类型完成了单列视图。

我的成功标准是:

  • 它可以支持非统一视图高度(每个自定义视图可以有自己的高度)
  • 只有一列,每个自定义视图都会随着视图大小的扩展而扩展。

进入源代码:

@interface ViewController ()
@property NSMutableArray *cellArray;
@property (weak) IBOutlet NSCollectionView *collectionView;

@end

@implementation ViewController

@synthesize cellArray;
@synthesize collectionView;

- (void)viewDidLoad {
    [super viewDidLoad];

    // Do any additional setup after loading the view.

    [collectionView registerClass:ItemOne.class forItemWithIdentifier:@"Item1"];
    [collectionView registerClass:ItemTwo.class forItemWithIdentifier:@"Item2"];

    cellArray = [@[@"Item1", @"Item2", @"Item1", @"Item2", @"Item1"] mutableCopy];
}


- (void)setRepresentedObject:(id)representedObject {
    [super setRepresentedObject:representedObject];

    // Update the view, if already loaded.
}

#pragma mark - NSCollectionViewDatasource -

- (NSInteger)numberOfSectionsInCollectionView:(NSCollectionView *)collectionView {
    return 1;
}

- (NSInteger)collectionView:(NSCollectionView *)collectionView
 numberOfItemsInSection:(NSInteger)section {

    // We are going to fake it a little.  Since there is only one section
    NSLog(@"Section: %ld, count: %ld", (long)section, [cellArray count]);

    return [cellArray count];
}

- (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView
 itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath {

    NSLog(@"IndexPath: %@, Requested one: %ld", indexPath, [indexPath item]);
    NSLog(@"Identifier: %@", [cellArray objectAtIndex:[indexPath item]]);

    NSCollectionViewItem *theItem = [collectionView makeItemWithIdentifier:[cellArray objectAtIndex:[indexPath item]] forIndexPath:indexPath];

    theItem.representedObject = [cellArray objectAtIndex:[indexPath item]];

    return theItem;
}

#pragma mark - NSCollectionViewDelegate -
- (NSSize)collectionView:(NSCollectionView *)collectionView
              layout:(NSCollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"%@", indexPath);

    NSSize size = NSMakeSize(438, 150);
    NSInteger width = 0;
    NSInteger height = 0;
    NSString *label = [cellArray objectAtIndex:[indexPath item]];

    NSRect collectionFrame = [collectionView frame];

    width = collectionFrame.size.width;

    // TODO: This needs to be based on the actual value of the view instead of hardcoding a number in.
    if ([label isEqualToString:@"Item1"]) {
        height = 114;
    } else if ([label isEqualToString:@"Item2"]) {
        height = 84;
    }

    size = NSMakeSize(width, height);

    return size;    
}

@end

好了。实施还算不错。 NSCollectionView 中显示的每个自定义视图都在其自己的 NSCollectionViewItem 和 .xib 文件中定义,因此它们很容易修改。

唯一脆弱的部分是我计算每个视图的高度的地方,它之所以脆弱,是因为我在示例应用程序的实现中懒惰了。在实际实现中,我将从实际视图中动态获取它们,这样它们就不会绑定到静态数字。