Objective c 为什么+;初始化被调用两次的核心数据管理对象的方法?

Objective c 为什么+;初始化被调用两次的核心数据管理对象的方法?,objective-c,core-data,Objective C,Core Data,我有一个带有+initialize方法的托管核心数据对象。(如果重要的话,我希望使用该方法初始化一个静态变量,而这个静态变量的设置成本很高。)在测试初始化代码时,我惊讶地发现+initialize方法被调用了两次 第一次调用initialize时,正如我所预料的那样,self被定义为(Class)MyClass 第二次调用initialize,self被定义为(Class)MyClass\u MyClass\ucode>,这让我怀疑核心数据管理对象的某种异常初始化 虽然这不会给我带来问题(我可以

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

第一次调用
initialize
时,正如我所预料的那样,self被定义为
(Class)MyClass

第二次调用
initialize
self
被定义为
(Class)MyClass\u MyClass\ucode>,这让我怀疑核心数据管理对象的某种异常初始化

虽然这不会给我带来问题(我可以测试静态变量是否已经初始化,我无论如何都会这样做,来处理ubclassing),但它让我怀疑核心数据在对象或类生命周期中做了一些我不理解的事情。有人能给我解释一下在这个
MyClass\u MyClass\ucode>
+initialize
方法调用中发生了什么吗?

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

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

为什么你不使用awakeFrom。。。方法
NSManagedObject
提供了?

核心数据属性的访问器方法是在运行时动态创建的。 这是通过创建一个子类
MyClass\u MyClass\u
(属于
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
的一个实例,但实际上是一个实例 动态创建的子类的。这个亚类
实现所有访问器方法(此实体特有)。

为了澄清,我理解+初始化,核心数据的实现似乎是在幕后创建对象的子类。我想知道这个子类在做什么。你可能想考虑使用<代码> +加载< /代码>,这不会重复调用。“Volker,我不太清楚如何醒来……方法会帮助我。我错过什么了吗?(另外,我可以很容易地使用+initialize来完成这项工作,这让我很惊讶,我不喜欢不了解额外子类的幕后工作。)@TomHarrington,谢谢你的想法。有趣的想法。我想我还是坚持使用initialize,因为很容易确保只初始化一次。And+load将把初始化推到生命周期的非常早期。@DavidOgren我在需要计算的某种瞬态数据中考虑了更多,因此考虑了类似
awakeFromInsert:
或'awakeFromFetch:例如的方法。“但我现在再仔细考虑一下,明白为什么这行不通了。”沃尔克。谢谢你的回答和思考。谢谢,这正是我的怀疑,但奇怪的是,我在任何地方都找不到通过动态创建的子类实现其动态访问器的核心数据的引用。在我开始研究这个问题之前,我一直认为动态方法是直接转换到
MyClass
类中的。@DavidOgren:methodswizzling只对每个类有效,而不是对每个实例有效。如果您有两个不同的实体,并且没有分配自定义类,那么通过swizzling实现附件将很困难,因为所有对象都是NSManagedObject的实例。-不幸的是,我没有一个明确的参考,它是这样工作的。我可能读过一些关于它的东西,但我不记得在哪里另一个指标可能是,当初始化子类时,您会在堆栈回溯中找到类似于
[NSManagedObject(\u PFDynamicAccessorsAndPropertySupport)classForEntity:
的内容。是的,这对我来说非常有意义。再次感谢。当我一开始考虑这个问题时,我已经忘记了没有自定义类可以swizzle的情况。