13

I've got two Entities that I'll call A and B. They are configured with To-Many relationships in both directions, so A.myBs and B.myAs are both NSSets.

Here is my bizarre problem.

When I add a B to my A entity, I do it using the mutableSetValueForKey like this:

NSMutableSet *myBSet = [myA mutableSetValueForKey:@"myBs"];
[myBSet addObject:theBtoAdd];

This does add the theBtoAdd to the A entity but does not add the inverse relationship. Core Data context save doesn't kick any errors, but my A object doesn't have the B inverse set. If I exit the application, even the partial relationship isn't saved.

Here's the strange part... if I just switch my code around and do the opposite (there are reasons why this is harder to do for my particular application) - add A to B instead of adding B to A like this:

NSMutableSet *myASet = [myB mutableSetValueForKey:@"myAs"];
[myASet addObject:theAtoAdd];

It works just fine. By the way, I have plenty of other to-many relationships that work. Just this one doesn't.

Couple of other things: 1) My core data object model looks good, but this is the first new entity that I've added under Xcode 4 2) I've check, rechecked and gone blind looking at my custom NSManagedObjects, but they look fine - declared dynamic, NSSet, no conflicting setters/getters... etc.

Any help or debugging suggestions would be greatly appreciated. Thank you!

vodkhang
  • 18,639
  • 11
  • 76
  • 110
p.pad
  • 529
  • 7
  • 11

3 Answers3

8

I just had the same problem, which was why I saw this question. Maybe my solution will help some people in the same situation.

For me the answer was that in the NSManagedObject subclass I had over-riden:

- (void)willChangeValueForKey:(NSString *)inKey withSetMutation:(NSKeyValueSetMutationKind)inMutationKind usingObjects:(NSSet *)inObjects

- (void)didChangeValueForKey:(NSString *)inKey withSetMutation:(NSKeyValueSetMutationKind)inMutationKind usingObjects:(NSSet *)inObjects

This prevents the correct notifications being sent to the parent class (NSManagedObject) which handles the automatic reverse relationships.

SimonB
  • 610
  • 8
  • 17
  • This helped me also. Remember to do the same also for -(void)didChangeValueForKey:(NSString *)key; (plain values) – Lukasz Sep 13 '12 at 21:24
  • Suuuch a dumb bug in my codebase, but this answer pointed out where the problem would be, so you've got my upvote. Thank you sir. – LeffelMania Jun 16 '14 at 06:20
  • Just to be clear. You can override them but you have to call super. I do it first thing. In Swift `super.didChangeValue(forKey: key) OR super.didChangeValue(forKey: inKey, withSetMutation: inMutationKind, using: inObjects) – Positron May 23 '23 at 17:28
3

I found the error, if you are overriding any of these methods

// KVO change notification
- (void)willChangeValueForKey:(NSString *)key;
- (void)didChangeValueForKey:(NSString *)key;
- (void)willChangeValueForKey:(NSString *)inKey withSetMutation:(NSKeyValueSetMutationKind)inMutationKind usingObjects:(NSSet *)inObjects;
- (void)didChangeValueForKey:(NSString *)inKey withSetMutation:(NSKeyValueSetMutationKind)inMutationKind usingObjects:(NSSet *)inObjects;

it will cause NSManagedObject don't work well and the relationships won't be set correctly

Apple documentation: You must not override these methods.

GOrozco58
  • 1,182
  • 12
  • 10
0

If you're subclassing the Managed Object, shouldn't there be auto-generated to-many relationship methods? So that you would just need to call:

[aObject addBObject:bObject];
Mark Leonard
  • 2,056
  • 19
  • 28
  • Yes, I can and did try that with the same result. I'm specifically following the advice in http://stackoverflow.com/questions/4206788/how-to-get-at-a-relationship-items-properties-in-core-data and using the mutableSetValueForKey. – p.pad Jun 02 '11 at 19:01