2014-04-07 34 views
2

我想了解子类如何在可可中工作。可可子类奇怪

我在XCode 5.1中创建了一个新的Cocoa应用程序项目。

我将一个新的自定义视图拖到主窗口上。

我创建了一个新的Objective-C类CustomViewClass并将其设置为NSView的子类。这将生成以下:

CustomViewClass.h
#import <Cocoa/Cocoa.h> 

@interface CustomViewClass : NSView 

@end 
CustomViewClass.m
#import "CustomViewClass.h" 

@implementation CustomViewClass 

- (id)initWithFrame:(NSRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     // Initialization code here. 
     NSLog(@"Custom View initialised"); 
    } 
    return self; 
} 

- (void)drawRect:(NSRect)dirtyRect 
{ 
    [super drawRect:dirtyRect]; 

    // Drawing code here. 
} 

@end 

请注意,我说的NSLog(@"Custom View initialised");线,所以我可以跟踪是怎么回事。

在界面构建器中,我选择自定义视图,并在标识检查器中将其设置为CustomView的自定义类。然后我运行该应用程序。

正如所料,我在控制台中收到Custom View initialised消息。

我做的正是用的NSTextField将它添加到窗口一样,创建一个新类TextFieldClass和的NSTextField自定义类是textFieldClass时。我还在上述相同的地方添加了一个NSLog(@"Text Field initialised");来跟踪事物。

但是,当我运行该应用程序时,我只收到控制台中的Custom View initialised消息,而不是NSLog(@"Text Field initialised");消息。

因此,最初我认为NSTextField在创建时不会收到initWithFrame消息。所以我添加一个到TextFieldClass的初始化程序:

- (id)init { 
    self = [super init]; 
    if (self) { 
     // Initialization code here. 
     NSLog(@"Text Field initialised"); 
    } 
    return self; 
} 

但是,这仍然不会被调用。

因此,我假定NSTextField只是不被子类化。然而,当我加入这个方法来TextFieldClass

-(void)textDidChange:(NSNotification *)notification { 
    NSLog(@"My text changed"); 
} 

运行的应用程序,你瞧,我每次在文本字段中键入时间,我得到的控制台My text changed消息。

所以我的问题是,这是怎么回事? NSTextField如何被初始化,以及如何覆盖它的初始化程序?

为什么自定义视图的行为似乎与NSTextField不同?

源代码here

回答

2

关于第一个问题,NSTextFiled得到通过

- (id)initWithCoder:(NSCoder *)aDecoder 

初始化在这种情况下,你已经拖从调色板中NSTextField,然后改变了类您的自定义文本字段级在身份检查员。因此将调用initWithCoder:而不是initWithFrame :.这同样适用于任何对象(而不是自定义视图等),真正从调色板

拖相反,如果从调色板中拖动“自定义视图”和类更改为您的自定义文本字段班,initWithFrame:将被调用。

CustomViewClass您创建是第二种情况,因此initWithFrame:被调用。 TextFieldClass是第一种情况,因此initWithCoder:被调用。

+0

没错,就是工作。你在哪里可以找到控制器的初始化者是什么?我查看了NSTextField的API参考,但未列出initWithCoder。 – dwkns

+0

你需要继续上去的继承..并检查超级类的文档.. initWithCoder:在NSObject中声明 –

1

如果您在XCode中使用Interface Builder,则应该使用awakeFromNib来初始化您的子类。

- (void)awakeFromNib 
{ 
    // Your init code here. 
} 

如果你想使用你的子类编程使用界面生成器,然后使用如下代码:

- (id)initWithFrame:(NSRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     [self initView]; 
    } 
    return self; 
}  

- (void)awakeFromNib 
{ 
    [self initView]; 
} 

- (void)initView 
{ 
    // Your init code here 
}