关于Objective C:如何在Cocoa应用程序中向NSWindow添加NSView?

How to add an NSView to NSWindow in a Cocoa app?

由于Xcode中的OS X应用程序模板似乎类似于空的应用程序模板,因此以下内容用于添加视图和按钮(暂时不使用"界面构建器"):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{      
    NSView *view = [[NSView alloc] initWithFrame:NSMakeRect(100, 100, 100, 100)];

    view.layer.backgroundColor = [[NSColor yellowColor] CGColor];

    [self.window.contentView addSubview:view];

    NSRect frame = NSMakeRect(10, 40, 90, 40);
    NSButton* pushButton = [[NSButton alloc] initWithFrame: frame];
    pushButton.bezelStyle = NSRoundedBezelStyle;

    [self.window.contentView addSubview:pushButton];

    NSLog(@"subviews are %@", [self.window.contentView subviews]);  
}

iOS上类似的代码应该产生一个黄色的框和一个按钮,但是上面的代码仅产生一个按钮,但是视图不会显示。上面的代码是否有问题,以及如何使其以黄色背景显示视图?


使用NSView类的setWantsLayer:方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
NSView *view = [[NSView alloc] initWithFrame:NSMakeRect(100, 100, 100, 100)];
[view setWantsLayer:YES];
view.layer.backgroundColor = [[NSColor yellowColor] CGColor];

[self.window.contentView addSubview:view];

NSRect frame = NSMakeRect(10, 40, 90, 40);
NSButton* pushButton = [[NSButton alloc] initWithFrame: frame];
pushButton.bezelStyle = NSRoundedBezelStyle;

[self.window.contentView addSubview:pushButton];

NSLog(@"subviews are %@", [self.window.contentView subviews]);


要扩展Kevin Ballard的建议,做到这一点的经典方法是将NSView子类化并覆盖-drawRect:方法。 NSRectFill是用于填充矩形而无需创建贝塞尔曲线路径的非常方便的功能:

1
2
3
4
5
- (void)drawRect:(NSRect)rect
{
    [[NSColor yellowColor] set];
    NSRectFill(rect);
}

默认情况下,可可中的

NSView不受层支持。我怀疑如果您键入

1
NSLog(@"%@", view.layer);

您将看到它是nil

在iOS中,所有视图都有图层。但是在OS X上,视图没有层次。另外,在OS X上有两种"模式"层支持视图。有所谓的"层支持视图"和"层托管视图"。层支持的视图使用CoreAnimation层来缓存绘制的数据,但不允许您以任何方式与该层进行交互。图层托管视图使用您显式提供的CALayer,并且您可能想要弄乱该图层。但是,对于图层宿主视图,您不能添加任何子视图,也不能使用内置的NSView绘制机制。图层托管视图只能用作CoreAnimation图层层次结构的根。

鉴于所有这些,您可能应该完全避免在视图中使用CoreAnimation。

NSBox可能会做您想要的事情。您当然可以在此处设置填充颜色,关闭边框,然后将样式设置为"自定义"。我只是不确定100%会将其绘制为简单的填充矩形颜色。或者,您可以定义自己的NSView子类,该子类在-drawRect:中绘制颜色。