我有一个+initialize
方法被多次调用,我不明白为什么。
根据文档,它将为每个类(以及子类)调用一次,
这是我正在使用的代码:
@interface MyClass : NSObject
@end
static NSArray *myStaticArray;
@implementation MyClass
+ (void)initialize
{
myStaticArray = [NSArray array];
}
@end
(显然还有其他代码,但这是相关部分)。
没有MyClass
的子类。它没有任何花哨的东西。当我的应用程序启动时,+ initialize被调用一次(NSApplication的委托告诉它用磁盘中的数据填充myStaticArray)。然后第二次调用+ initialize,这是用户第一次选择与此类相关的菜单项。
我只是在我的dispatch_once()
代码周围添加了initialize
,这显然解决了我的问题。但是我不明白发生了什么事?当没有子类时,为什么会多次调用它?
这是第一次调用初始化时的堆栈跟踪:
+[MyClass initialize]
_class_initialize
objc_msgSend
-[MyAppDelegate applicationDidBecomeActive:]
_CFXNotificationPost
NSApplicationMain
main
start
这是第二个电话:
+[MyClass initialize]
_class_initialize
NSApplicationMain
main
start
正如您所看到的,我的代码似乎没有触发第二次调用+ initialize(堆栈跟踪中没有任何内容)。它会在之后立即出现我显示一个窗口,该窗口显示由+initialize
清除的静态数组的内容(窗口显示数组内容,但在此之后数组为空)。
答案 0 :(得分:24)
+initialize
将在第一次引用时(通过消息)发送到每个类,包括动态创建的类。运行时没有保护措施防止多次触发执行。如果一个子类被初始化,但没有实现+initialize
,那么链上的任何super
将会再次调用它们。
正交地,自动KVO是通过创建被观察实例的类的动态派生子类来实现的。该子类是+initialize
d,就像任何其他类一样,从而触发父类+initialize
的多次执行。
运行时可以采取措施来防止这种情况发生。但是,由于+initialize
一直被记录为可能被执行多次,这增加了复杂性(考虑到KVO类频繁出入,可能是非常复杂的)并不值得付出努力。
目前推荐的模式是:
+ (void) initialize
{
static dispatch_once_t once;
dispatch_once(&once, ^{
... one time initialization here ...
});
}
答案 1 :(得分:3)
+initialize
,因此如果初始化两个共享相同超类(或超类及其子类之一)的类,则超类“+initialize
方法会被叫两次。
这可能是原因吗?
答案 2 :(得分:0)
1.Runtime在子类
之前调用超类中的+ initialize方法2.如果子类没有方法,那么它将调用父类初始化方法。
3.使用始终记载方法的chronicle方法 +(无效)初始化{
if(self==[Car Class]){
//initialize here your static var
}
}
清楚了解阅读此帖+(void)initialize