2014-04-07 5 views
2

Я пытаюсь понять, как работает подклассификация в какао.Какао Подклассическая странность

Я создал новый проект приложений какао в XCode 5.1.

Я перетащил новый пользовательский вид в главное окно.

Я создаю новый класс Objective-C CustomViewClass и устанавливаю его как подкласс NSView. Это порождает следующее: что я добавил NSLog(@"Custom View initialised"); линию таким образом я могу отслеживать, что происходит на

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 

Примечание.

В интерфейсе Builder я выбираю пользовательский вид, а внутри Idenditiy Inspecter установлен его собственный класс для 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 из палитры, а затем изменил класс пользовательского класса текстового поля в инспекторе идентификации. Следовательно, вместо initWithFrame будет вызываться initWithCoder:.То же самое верно для любого объекта (кроме пользовательского вида), перетаскиваемого из палитры.

Вместо этого, если вы перетащите «Пользовательский вид» из палитры и измените класс на свой собственный класс текстового поля, вызывается initWithFrame:.

CustomViewClass Вы создали второй случай, поэтому вызывается initWithFrame:. TextFieldClass - это первый случай, поэтому вызывается initWithCoder:.

+0

Да, это работает. Где вы можете узнать, что такое инициализаторы для элемента управления? Я просмотрел ссылку API для NSTextField, но initWithCoder не указан. – dwkns

+0

Вам нужно продолжать идти по наследству .. и проверить документацию суперкласса .. initWithCoder: объявлен в NSObject –

1

Если вы используете Interface Builder в XCode, вы должны использовать 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 
} 
Смежные вопросы