2

So I've just converted my Core Data model to code so it can easily fit into a static library. Unfortunately its not a smooth conversion.

I'm getting this error when trying to insert a new Player as a relationship for another class named gameToPlayer.

Unacceptable type of value for to-one relationship: property = "player"; desired type = (null); given type = Player; value = <Player: 0x178ba9e0>

Here is the GameToPlayer creation:

    gameToPlayerEntity = [[NSEntityDescription alloc] init];
    [gameToPlayerEntity setName:@"GameToPlayer"];
    [gameToPlayerEntity setManagedObjectClassName:@"GameToPlayer"];

    gameToPlayerPlayer = [[NSRelationshipDescription alloc] init];
    [gameToPlayerPlayer setDestinationEntity:playerEntity];
    [gameToPlayerPlayer setInverseRelationship:playerGames];
    [gameToPlayerPlayer setDeleteRule:NSNullifyDeleteRule];
    [gameToPlayerPlayer setOptional:YES];
    [gameToPlayerPlayer setName:@"player"];
    [gameToPlayerPlayer setMaxCount:1];
    [gameToPlayerPlayer setMinCount:1];

And the Player creation:

    playerEntity = [[NSEntityDescription alloc] init];
    [playerEntity setName:@"Player"];
    [playerEntity setManagedObjectClassName:@"Player"];

    playerGames = [[NSRelationshipDescription alloc] init];
    [playerGames setDestinationEntity:gameToPlayerEntity];
    [playerGames setInverseRelationship:gameToPlayerPlayer];
    [playerGames setDeleteRule:NSCascadeDeleteRule];
    [playerGames setName:@"games"];
    [playerGames setOptional:YES];
    [playerGames setMaxCount:0];
    [playerGames setMinCount:0];

And where the crash is occurring (Sorry for the all the NSLogs was using them to track this down) It stops where we set the player:

    NSLog(@"Create the GameToPlayer");
    GameToPlayer *orderObj = [NSEntityDescription insertNewObjectForEntityForName:@"GameToPlayer" inManagedObjectContext:[SDDataManager dataManager].managedObjectContext];
    NSLog(@"Set the Game");
    [orderObj setGame:newGame];
    NSLog(@"Set the Player");
    [orderObj setPlayer:player];
    NSLog(@"Set the Order");
    [orderObj setOrder:[NSNumber numberWithInt:[selectedPlayers indexOfObject:player]]];
    NSLog(@"Add to Array");
    [orderObjs addObject:orderObj];

Now I actually think I know the problem. In the custom init for my ManagedObjectModel. the gameToPlayerEntity is created before the playerEntity. So the playerEntity is actually NULL when the gameToPlayerEntity is created. However I can't simply reorder, make them properties, or do anything to fix it because if I change anything in the file it seems its no longer able to map the existing database...

And I can't find anywhere in the documentation, that shows how to version code models like xml models which I expect to be the problem. Any help or tips appreciated. Just trying to get a handle on how to get this working.

Update

Figured its worth mentioning that prior to this conversion I was already using lightweight migration and was on the 4th iteration of the database.

enter image description here

Update 2

I've been able to get it working by starting completely over. instead of trying to move on from what's been posted. Everything has been converted to properties so that each entity is create when needed and only once. This works as a conversion from Visual Model to Code Model. However I will definitely need to understand versioning in the future when this model inevitably changes. Versioning is the root of this problem to start with. So if anyone can shed some light on how one would go about versioning without using the xcode interface I'd love to hear your thoughts.

Ryan Poolos
  • 18,421
  • 4
  • 65
  • 98

2 Answers2

2

I don't think this was necessarily your problem, but I do want to post this other possibility for folks who also get this error. If you see this error while moving data from one persistent store to another (for example, moving from a fallback store to an iCloud store), it's likely that the NSEntityDescription you're using to create your new managed object is from your old copy of the object (and therefore the wrong managed object context).

When you're doing your code like:

NSEntityDescription *entity = [oldObj entity];
YourClass *newObj = [[YourClass alloc] initWithEntity:entity
                       insertIntoManagedObjectContext:moc];

You need to take the extra step of getting the entity description from the context you're inserting into.

NSEntityDescription *entity = [oldObj entity];
NSEntityDescription *goodEntity = [NSEntityDescription entityForName:entity.name
                                              inManagedObjectContext:moc];
YourClass *newObj = [[YourClass alloc] initWithEntity:goodEntity
                                       insertIntoManagedObjectContext:moc];

Credit to Pavel Kapinos for his note on the Cocoa Dev email list. http://www.mail-archive.com/cocoa-dev@lists.apple.com/msg24863.html

Kelly
  • 1,096
  • 12
  • 22
0

Would it be too hard to initialize the entities and relationships in the begining of the method and then set all the properties?

playerEntity = [[NSEntityDescription alloc] init];
gameToPlayerEntity = [[NSEntityDescription alloc] init];
gameToPlayerPlayer = [[NSRelationshipDescription alloc] init];

Then at some point later in the method:

[gameToPlayerPlayer setDestinationEntity:playerEntity];
  • No of course not, but sadly if I even move the declarations Core Data complains the model has changed. If you could point me to how to set up versioning in code models similar to how you set up versioning for visual models then I suppose it wouldn't be a problem. – Ryan Poolos Aug 20 '12 at 15:36