CoreData: error: Failed to call designated initial

2019-01-08 22:09发布

问题:

I have a little damn problem with CoreData. I want to insert a new Object, so I first have to create one. This is done by that code:

Challenges *newChallenge = [[Challenges alloc] init];
[newChallenge setName:@"TestChallenge"];
[newChallenge setRounds:[[NSNumber alloc] initWithInt:12]];
[newChallenge setShots:[[NSNumber alloc] initWithInt:5]];
[newChallenge setDate:[NSDate date]];

But however after the alloc init I get this error:

CoreData: error: Failed to call designated initializer on NSManagedObject class 'Challenges'

What the hack is going wrong?

回答1:

I think the problem is that Challenges is a NSManagedObject class and you need the designated initializer:

initWithEntity:insertIntoManagedObjectContext:

instead of

Challenges *newChallenge = [[Challenges alloc] init];

Read More..



回答2:

In case you ask yourself "OK, so how to I get that entity?" (like I did), you do this by using the entityForName method like so:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Challenges" inManagedObjectContext:self.managedObjectContext];

Challenges *newChallenge = [[Challenge alloc] initWithEntity:entity insertIntoManagedObjectContext:self.managedObjectContext];

Hope this helps, this thread has helped me a lot!



回答3:

NSManagedObject cannot be just alloc/init like you would normally do with an NSObject. As a matter of fact the designated initializer is: initWithEntity:insertIntoManagedObjectContext:

Now, for the actual error, Apple states in the documentation that:

Important: This method is the designated initializer for NSManagedObject. You must not initialize a managed object simply by sending it init.

So, you could see that you need 2 things in order to initialize it, an NSEntityDescription (which entity you intend to instantiate) and an NSManagedObjectContext (the context that the new object will be created into).



回答4:

Others have already stated why its not working. Here is how you can cut down on the boilerplate and make your code more readable:

@implementation NSManagedObject(MyPrivateAdditions)

+ (id)insertNewObjectInContext:(NSManagedObjectContext *)context
{
    return [NSEntityDescription insertNewObjectForEntityForName:self.className inManagedObjectContext:context];
}

@end

now you can do:

Challenges *newChallenge = [Challenge insertNewObjectInContext:context];


回答5:

Additionaly, if your Challenges class is NSManagedObject and date, rounds and shots are defined as its attributes you can add method:

-(void) awakeFromInsert {
     self.date = [NSDate date];
     self.rounds = @(12);
     self.shots = @(5);
}

Each new object will have defined those attributes from its birth.