xcode - 如何从头开始以编程方式创建 NSCollectionView?

标签 xcode cocoa nscollectionview

NSCollectionView 仍然是我所见过的 Cocoa API 中最神秘的部分之一。文档很差,并且有许多移动部件,其中许多通常在 Interface Builder 中实现,这使得文档变得具有挑战性。

请提供示例代码来创建最简单的 NSCollectionView 案例,该案例显示文本字段或按钮,而无需使用 Xcode,其中每个文本字段或按钮都有不同的标题。假设一个新的 Xcode 项目具有默认的窗口 IBOutlet。

对于此示例,无需绑定(bind)即可在数据源更改时更新 NSCollectionView。只需显示原型(prototype)对象网格并将每个对象的标题设置为某个值即可。

如果我们能为很多人提供一个很好的例子来说明如何做到这一点,我认为这将帮助每个使用 NSCollectionViews 并像我一样困惑的人。

请求摘要

  • 提供示例代码以在新的 Xcode 项目中渲染 NSCollectionView
  • 不要使用Interface Builder,请使用提供的默认窗口IBOutlet
  • NSCollectionView 应包含文本字段或按钮,您可以选择
  • View 中的每个项目都应该有不同的标题
  • 无需绑定(bind)

如果有满足这些要求的示例代码,请提供一个链接,那就太好了!

最佳答案

我不确定以编程方式创建 Collection View 而不需要绑定(bind)是否有很多见解,但它就是这样。

简介

使用 Collection View 时基本上有四个组件:

  • View:NSView的子类,负责显示信息;
  • Collection View 本身;
  • View Controller :NSCollectionViewItem 的子类,用作 Collection View 项原型(prototype);
  • 模型:对象数组。

通常, View 是在 Interface Builder 中设计的,模型是通过 Cocoa 绑定(bind)来调节的。

以编程方式执行:

常量

static const NSSize buttonSize = {80, 20};
static const NSSize itemSize = {100, 40};
static const NSPoint buttonOrigin = {10, 10};

查看

这是一个包含按钮的标准 View (Interface Builder 中的自定义 View )。请注意, View 具有固定大小。

@interface BVView : NSView
@property (weak) NSButton *button;
@end

@implementation BVView
@synthesize button;
- (id)initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:(NSRect){frameRect.origin, itemSize}];
    if (self) {
        NSButton *newButton = [[NSButton alloc] 
            initWithFrame:(NSRect){buttonOrigin, buttonSize}];
        [self addSubview:newButton];
        self.button = newButton;
    }
    return self;
}
@end

View Controller (原型(prototype))

通常, View Controller 从 nib 文件加载其 View 。在极少数情况下, View Controller 无法从 nib 文件获取其 View ,开发人员必须在 View 接收 -view 之前发送 -setView: Controller ,或覆盖 -loadView。以下代码执行后者。

View Controller 通过-setRepresentedObject:接收相应的模型对象。我已经重写了它,以便在模型对象发生更改时更新按钮标题。请注意,这可以通过使用 Cocoa 绑定(bind)来完成,而无需任何代码。

请注意,这些代码都不是特定于 Collection View 的 - 这是一般 View Controller 的行为。

@interface BVPrototype : NSCollectionViewItem
@end

@implementation BVPrototype
- (void)loadView {
    [self setView:[[BVView alloc] initWithFrame:NSZeroRect]];
}
- (void)setRepresentedObject:(id)representedObject {
    [super setRepresentedObject:representedObject];
    [[(BVView *)[self view] button] setTitle:representedObject];
}
@end

型号

表示按钮标题的简单字符串数组:

@property (strong) NSArray *titles;
self.titles = [NSArray arrayWithObjects:@"Case", @"Molly", @"Armitage",
    @"Hideo", @"The Finn", @"Maelcum", @"Wintermute", @"Neuromancer", nil];

Collection View

到目前为止,唯一建立的关系是项目原型(prototype) (BVPrototype) 使用的 View (BVView)。必须告知 Collection View 它应该使用的原型(prototype)以及从中获取数据的模型。

NSCollectionView *cv = [[NSCollectionView alloc]
    initWithFrame:[[[self window] contentView] frame]]; 
[cv setItemPrototype:[BVPrototype new]];
[cv setContent:[self titles]];

应用程序委托(delegate)的完整源代码

#import "BVAppDelegate.h"


static const NSSize buttonSize = { 80, 20 };
static const NSSize itemSize = { 100, 40 };
static const NSPoint buttonOrigin = { 10, 10 };


@interface BVView : NSView
@property (weak) NSButton *button;
@end

@implementation BVView
@synthesize button;
- (id)initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:(NSRect){frameRect.origin, itemSize}];
    if (self) {
        NSButton *newButton = [[NSButton alloc]
            initWithFrame:(NSRect){buttonOrigin, buttonSize}];
        [self addSubview:newButton];
        self.button = newButton;
    }
    return self;
}
@end


@interface BVPrototype : NSCollectionViewItem
@end

@implementation BVPrototype
- (void)loadView {
    [self setView:[[BVView alloc] initWithFrame:NSZeroRect]];
}
- (void)setRepresentedObject:(id)representedObject {
    [super setRepresentedObject:representedObject];
    [[(BVView *)[self view] button] setTitle:representedObject];
}
@end


@interface BVAppDelegate ()
@property (strong) NSArray *titles;
@end

@implementation BVAppDelegate

@synthesize window = _window;
@synthesize titles;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    self.titles = [NSArray arrayWithObjects:@"Case", @"Molly", @"Armitage",
        @"Hideo", @"The Finn", @"Maelcum", @"Wintermute", @"Neuromancer", nil];

    NSCollectionView *cv = [[NSCollectionView alloc]
        initWithFrame:[[[self window] contentView] frame]]; 
    [cv setItemPrototype:[BVPrototype new]];
    [cv setContent:[self titles]];

    [cv setAutoresizingMask:(NSViewMinXMargin
                             | NSViewWidthSizable
                             | NSViewMaxXMargin
                             | NSViewMinYMargin
                             | NSViewHeightSizable
                             | NSViewMaxYMargin)];
    [[[self window] contentView] addSubview:cv];
}

@end

关于xcode - 如何从头开始以编程方式创建 NSCollectionView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8660626/

相关文章:

cocoa - NSCollectionView 类似延迟加载的行为

objective-c - NSCollectionView 中的悬停效果

swift - NSCollectionView `validateDrop` 委托(delegate)未被调用

c++ - Xcode C++ 错误 "linker command failed with exit code 1"

Swift ViewController 不响应 -getFile,无法连接操作,目标类

ios - 在设备控制台中查看 os_log 消息

vb.net - XCode Cocoa 问题(VB.NET 到 Cocoa)

swift - 如何在 NSDatePicker 图形模式中设置颜色

c++ - macOS 塞拉利昂 : __textcoal__nt is deprecated

ios - 无法按产品标识从数组中找到SKProduct