Reputation: 4800
I have a managed core data object with a +initialize
method. (If it matters, I am looking to use that method to initialize a static variable that is expensive to to set up.) While testing that initialization code I was surprised to discover that the +initialize
method is getting called twice.
The first time initialize
is being called self
is defined as (Class) MyClass
, as I would expect.
The second time initialize
is being called self
is defined as (Class) MyClass_MyClass_
, which leads me to suspect some sort of unusual initialization for Core Data managed objects.
While this doesn't pose a problem for me (I can just test to see if the static variable has already been initialized, which I would do anyway, to handle ubclassing), it makes me suspect that Core Data is doing something in the object or class lifecycle that I don't understand. Can someone explain to me what is going on in this MyClass_MyClass_
+initialize
method invocation?
Upvotes: 4
Views: 550
Reputation: 539815
The accessor methods for Core Data properties are dynamically created at runtime.
This works by creating a subclass MyClass_MyClass_
(of MyClass
) and adding the
necessary methods to the subclass.
Core Data also does some tricks to hide the fact that that the objects of your entity are actually instances of the subclass:
e = [NSEntityDescription insertNewObjectForEntityForName:@"MyClass" inManagedObjectContext:context];
NSLog(@"%@", [e class]); // --> MyClass
NSLog(@"%s", object_getClassName(e)); // --> MyClass_MyClass_
Perhaps it becomes even more obvious if you don't set a custom class for your entity. In that case the output is
NSLog(@"%@", [e class]); // --> NSManagedObject
NSLog(@"%s", object_getClassName(e)); // --> NSManagedObject_MyClass_
So e
"looks like" an instance of NSManagedObject
, but is indeed an instance
of a dynamically created subclass NSManagedObject_<EntityName>_
. This subclass
implements all the accessor methods (which are unique to this entity).
Upvotes: 5
Reputation: 4660
From Apples documentation on NSObject
I gather it is normal behaviour: The runtime sends initialize to each class in a program just before the class, or any class that inherits from it, is sent its first message from within the program. The runtime sends the initialize message to classes in a thread-safe manner. Superclasses receive this message before their subclasses. The superclass implementation may be called multiple times if subclasses do not implement initialize—the runtime will call the inherited implementation—or if subclasses explicitly call [super initialize]. If you want to protect yourself from being run multiple times, you can structure your implementation along these lines...
+ (void)initialize {
if (self == [ClassName class]) {
// ... do the initialization ...
}
}
Why you don't use the awakeFrom... methods NSManagedObject
offers?
Upvotes: 0