2014-04-07 35 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 
}