NSCollectionView正在相互绘制NSCollectionViewItems

时间:2017-06-17 05:00:49

标签: objective-c macos autolayout nscollectionview nscollectionviewitem

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

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

更新 我当前的示例有两个视图,这两个视图当前在自己的nib文件中,具有专用的NScollectionViewItem对象,它们当前用于测试。我基本上有一个NSCollectionViewItem,它的子视图中包含NSTextField。有了所有的限制。

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

为了使用Data加载它我使我的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中的view属性与NSCollectionViewItem相关联。除了默认值

之外,目前没有任何限制

NSCollectionView网格设置如下:

  

布局:网格尺寸:最大行数:0最大列数:1最小项目大小:   宽度:250高度:150最大物品尺寸:宽度:250高度:150

这是用于设置整个事物的代码,此时不将其绑定到数据源。

似乎无论我更改设置甚至将CollectionView类型更改为Flow都不会改变任何内容,它看起来都是一样的。

我一直认为这是一个AutoLayout问题,因为最初存在一些自动布局问题,但这些都已经解决了。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

数据数组应保存数据而不是@(...) s。在NSCollectionViewItem中,您拨打collectionView:itemForRepresentedObjectAtIndexPath:。致电makeItemWithIdentifier:forIndexPath:registerClass:forItemWithIdentifier:注册您的班级或笔记。

NSCollectionViewcollectionView:itemForRepresentedObjectAtIndexPath:makeItemWithIdentifier:forIndexPath:文档中的详细信息。

编辑:

有两种方法可以提供registerNib:forItemWithIdentifier:

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

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

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

答案 1 :(得分:0)

我知道了。

并制作了一个带有工作版Working Version of Collection View Sample Application

的github仓库

第一件事。感谢Willeke对原始xib设置方式的捕捉,我能够使Grid类型工作。但最终,如果你可以让它做你想做的事情,那么Grow视图是一种更好的视图类型,因为它支持部分和视图之间的距离等。所以尽管我开始想要使用Grid类型我将要实现我的应用程序中的Grow类型。

所以我使用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文件中定义,因此它们很容易修改。

脆弱的唯一部分是我计算每个视图的高度的地方,它只是脆弱的,因为我在示例应用程序的实现中很懒。在实际实现中,我将从实际视图中动态获取它们,这样它们就不会与静态数字相关联。