我正在尝试子类化NSOutlineView。这是我的代码:
OutlineViewSublcass.h:
#import <Cocoa/Cocoa.h>
@interface OutlineViewSubclass : NSOutlineView {
}
@end
OutlineViewSubclass.m:
#import "OutlineViewSubclass.h"
@implementation OutlineViewSubclass
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
printf("debug A\n");
return self;
}
- (void)awakeFromNib
{
printf("debug B\n");
}
@end
调试输出为:
debug B
为什么不调用(id)initWithFrame:(NSRect)frame
?
答案 0 :(得分:50)
Cocoa控件实现了NSCoding协议,用于从nib中取消归档。 initWithCoder:方法不是使用initWithFrame初始化对象,然后设置属性,而是负责在使用Interface Builder配置的序列化属性加载控件时设置控件。这与使用NSCoding序列化任何对象的方式非常相似。
如果你在一个没有实现NSCoding的nib中粘贴一个自定义的NSView子类,那会有点不同,在这种情况下会调用initWithFrame:在这两种情况下,都会在加载对象后调用awakeFromNib,这通常是在子类中执行其他初始化的好地方。
答案 1 :(得分:18)
Apple的官方答案是Creating a Custom View。
查看在Interface Builder中创建的实例不要调用initWithFrame:加载其nib文件时,这通常会导致混淆。请记住,Interface Builder在保存nib文件时归档对象,因此已经创建了视图实例,并且已经调用了initWithFrame:。
awakeFromNib方法提供了一个机会,可以在加载nib文件时创建视图的初始化。当加载包含视图对象的nib文件时,每个视图实例在取消归档所有对象时都会收到awakeFromNib消息。这为对象提供了初始化未使用Interface Builder中的对象存档的任何属性的机会。