如何从头编程创建NSCollectionView? [英] How to create NSCollectionView programatically from scratch?

查看:514
本文介绍了如何从头编程创建NSCollectionView?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



对于这个例子, NSCollectionView作为数据源的变化。只需显示原型对象的网格,并将每个对象的标题设置为某个值即可。



如果我们能够得到一个很好的例子,它将帮助所有使用 NSCollectionViews 的人,并像我一样感到困惑。



请求摘要




  • 提供示例代码以在新的Xcode项目中呈现NSCollectionView

  • 不使用Interface Builder,请使用IBOutlet提供的默认窗口

  • NSCollectionView应包含文本字段或按钮,您的选择

  • 视图中的每个项目有不同的标题

  • 不需要绑定



解决方案



/ div>

我不确定是否通过编程方式创建集合视图并且没有绑定,但在这里它有很多洞察力。



简介



使用集合视图时,基本上有四个组件:




  • 视图: NSView ,负责显示信息;

  • 集合视图本身;

  • 视图控制器: c $>

  • NSCollectionViewItem


通常一个视图是在Interface Builder中设计的,一个模型是由Cocoa绑定的。



程序化:



常量



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



查看



(Interface Builder中的自定义视图)包含一个按钮。注意,视图有固定的大小。

  @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)



通常,视图控制器从nib文件加载其视图。在极少数情况下,视图控制器不能从nib文件获取其视图,开发人员必须在之前发送 -setView: 被视图控制器接收,或者覆盖 -loadView 。以下代码执行后者。



视图控制器通过 -setRepresentedObject:接收相应的模型对象。我已经覆盖它,以便更新按钮标题时,模型对象更改。注意,这可以通过使用没有任何代码的Cocoa绑定来实现。



请注意,这些代码都不是特定于集合视图的 - 这是一般的视图控制器行为。 / p>

  @interface BVPrototype:NSCollectionViewItem 
@end

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



模型


b $ b

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

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



集合视图



已建立的唯一关系是项目原型( BVPrototype )使用的视图( BVView )。必须通知收集视图应使用的原型以及从中获取数据的模型。

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



应用程序代理的完整源代码



  #importBVAppDelegate.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 )resentObject {
[super setRepresentedObject:representedObject];
[[(BVView *)[self view] button] setTitle :resentObject];
}
@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


NSCollectionView remains one of the most mysterious parts of the Cocoa API that I've ever seen. Documentation is poor and there are many moving parts, many of which are often implemented in Interface Builder, making documentation challenging.

Please provide sample code to create the simplest case of NSCollectionView which displays either Text Fields or Buttons without using Xcode where each Text Field or Button has a different Title. Assume a new Xcode project with the default window IBOutlet.

For this example, no binding is required to update the NSCollectionView as the data source changes. Simply display a grid of prototype objects and set each object's Title to some value.

If we can get a good example of how to do this available to many people, I think it will help everyone who works with NSCollectionViews and is as baffled as I am.

Summary of request

  • Provide sample code to render an NSCollectionView in a new Xcode project
  • Do not use Interface Builder, do use the default window IBOutlet provided
  • NSCollectionView should contain Text Fields or Buttons, your choice
  • Each item in the view should have a different Title
  • No binding is required

If there's sample code out there that meets these requirements, please provide a link, that'd be great!

Thanks!

解决方案

I’m not sure there’s much insight in creating a collection view programmatically and without bindings, but here it goes.

Introduction

There are essentially four components when using a collection view:

  • View: a subclass of NSView, responsible for displaying information;
  • The collection view itself;
  • View controller: a subclass of NSCollectionViewItem that serves as the collection view item prototype;
  • Model: an array of objects.

Usually a view is designed in Interface Builder, and a model is mediated by Cocoa bindings.

Doing it programmatically:

Constants

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

View

This is a standard view (a custom view in Interface Builder parlance) containing a button. Note that the view has fixed size.

@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)

Normally a view controller loads its view from a nib file. In the rare cases where the view controller doesn’t obtain its view from a nib file, the developer must either send it -setView: before -view is received by the view controller, or override -loadView. The following code does the latter.

View controllers receive the corresponding model object via -setRepresentedObject:. I’ve overridden it so as to update the button title whenever the model object changes. Note that this can be accomplished by using Cocoa bindings without any code at all.

Note that none of this code is specific to collection views — it’s general view controller behaviour.

@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

Model

A simple array of strings representing button titles:

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

Collection View

So far, the only relation that’s been established is the view (BVView) used by the item prototype (BVPrototype). The collection view must be informed of the prototype it should be using as well as the model from which to obtain data.

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

Full Source Code for the Application 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

这篇关于如何从头编程创建NSCollectionView?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆