为什么核心数据托管对象的 +initialize 方法被调用两次



我有一个带有+initialize方法的托管核心数据对象。(如果这很重要,我希望使用该方法来初始化一个设置成本很高的静态变量。在测试初始化代码时,我惊讶地发现+initialize方法被调用了两次。

正如我所期望的那样,initialize第一次被称为self被定义为(Class) MyClass

第二次调用initializeself被定义为(Class) MyClass_MyClass_,这让我怀疑核心数据托管对象的某种异常初始化。

虽然这对我来说不会造成问题(我可以测试静态变量是否已经初始化,无论如何我都会这样做来处理 ubclassing),但它让我怀疑 Core Data 正在对象或类生命周期中做一些我不理解的事情。有人可以向我解释一下这个MyClass_MyClass_ +initialize方法调用中发生了什么吗?

核心数据属性的访问器方法是在运行时动态创建的。这通过创建一个子类 MyClass_MyClass_ (的 MyClass ) 并添加子类的必要方法。

核心数据也做了一些技巧来隐藏事实实体的对象实际上是子类的实例:

e = [NSEntityDescription insertNewObjectForEntityForName:@"MyClass" inManagedObjectContext:context];
NSLog(@"%@", [e class]);               // --> MyClass
NSLog(@"%s", object_getClassName(e));  // --> MyClass_MyClass_

如果不为实体设置自定义类,也许会变得更加明显。在这种情况下,输出为

NSLog(@"%@", [e class]);               // --> NSManagedObject
NSLog(@"%s", object_getClassName(e));  // --> NSManagedObject_MyClass_

所以e"看起来像"NSManagedObject的实例,但确实是一个实例的动态创建的子类NSManagedObject_<EntityName>_ 。此子类实现所有访问器方法(此实体是唯一的)。

从 Apple 关于 NSObject 的文档中,我收集到这是正常行为:运行时在类或从它继承的任何类从程序内发送其第一条消息之前,向程序中的每个类发送初始化。运行时以线程安全的方式将初始化消息发送到类。超类在其子类之前接收此消息。如果子类不实现初始化(运行时将调用继承的实现),或者子类显式调用 [super initialize],则可以多次调用超类实现。如果你想保护自己不被多次运行,你可以按照这些思路构建你的实现......

+ (void)initialize {
    if (self == [ClassName class]) {
    // ... do the initialization ...
   }
}

为什么你不使用唤醒从...NSManagedObject提供的方法?

最新更新