Note that there are some explanatory texts on larger screens.

plurals
  1. PODoes CoreData allow object graph loops? (Strange error)
    primarykey
    data
    text
    <p>I've been having a strange problem with CoreData for a while now. This will be a lenghty question, so bear with me... </p> <p>I have two Entites, call them A and B. B might be both creator and updater of several A's. A must have a B as creator, and may or may not have a B as updater. (Required and optional relationships.) </p> <p>B might have both created and updated zero or more A's. </p> <p><img src="https://i.stack.imgur.com/HT14k.png" alt="With inverse relationships"></p> <p>The above is the data model I built. (I don't really <em>need</em> the inverse relationship from B to A, but CoreData gives me compile time warnings otherwise.) </p> <p><strong>EDIT</strong></p> <p>Here are the relevant parts of the ManagedObject subclasses: </p> <p>A.h</p> <pre><code>@property (nonatomic, retain) B * creator; @property (nonatomic, retain) B * updater; </code></pre> <p>A.m</p> <pre><code>@dynamic creator; @dynamic updater; </code></pre> <p>B.h</p> <pre><code>@property (nonatomic, retain) NSSet * created; @property (nonatomic, retain) NSSet * updated; </code></pre> <p>B.m</p> <pre><code>@dynamic updated; @dynamic created; - (void)addUpdatedObject:(A *)value { NSSet *changedObjects = [[NSSet alloc] initWithObjects:&amp;value count:1]; [self willChangeValueForKey:@"updated" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects]; [[self primitiveValueForKey:@"updated"] addObject:value]; [self didChangeValueForKey:@"updated" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects]; [changedObjects release]; } - (void)removeUpdatedObject:(A *)value { NSSet *changedObjects = [[NSSet alloc] initWithObjects:&amp;value count:1]; [self willChangeValueForKey:@"updated" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects]; [[self primitiveValueForKey:@"updated"] removeObject:value]; [self didChangeValueForKey:@"updated" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects]; [changedObjects release]; } - (void)addUpdated:(NSSet *)value { [self willChangeValueForKey:@"updated" withSetMutation:NSKeyValueUnionSetMutation usingObjects:value]; [[self primitiveValueForKey:@"updated"] unionSet:value]; [self didChangeValueForKey:@"updated" withSetMutation:NSKeyValueUnionSetMutation usingObjects:value]; } - (void)removeUpdated:(NSSet *)value { [self willChangeValueForKey:@"updated" withSetMutation:NSKeyValueMinusSetMutation usingObjects:value]; [[self primitiveValueForKey:@"updated"] minusSet:value]; [self didChangeValueForKey:@"updated" withSetMutation:NSKeyValueMinusSetMutation usingObjects:value]; } - (void)addCreatedObject:(A *)value { NSSet *changedObjects = [[NSSet alloc] initWithObjects:&amp;value count:1]; [self willChangeValueForKey:@"created" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects]; [[self primitiveValueForKey:@"created"] addObject:value]; [self didChangeValueForKey:@"created" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects]; [changedObjects release]; } - (void)removeCreatedObject:(A *)value { NSSet *changedObjects = [[NSSet alloc] initWithObjects:&amp;value count:1]; [self willChangeValueForKey:@"created" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects]; [[self primitiveValueForKey:@"created"] removeObject:value]; [self didChangeValueForKey:@"created" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects]; [changedObjects release]; } - (void)addCreated:(NSSet *)value { [self willChangeValueForKey:@"created" withSetMutation:NSKeyValueUnionSetMutation usingObjects:value]; [[self primitiveValueForKey:@"created"] unionSet:value]; [self didChangeValueForKey:@"created" withSetMutation:NSKeyValueUnionSetMutation usingObjects:value]; } - (void)removeCreated:(NSSet *)value { [self willChangeValueForKey:@"created" withSetMutation:NSKeyValueMinusSetMutation usingObjects:value]; [[self primitiveValueForKey:@"created"] minusSet:value]; [self didChangeValueForKey:@"created" withSetMutation:NSKeyValueMinusSetMutation usingObjects:value]; } </code></pre> <p><strong>END EDIT</strong></p> <p>When I create a new A with a B as creator, everything is fine (when using inverse relationships). However, when I update that same A later, using the same B as creator, i get the following crash: </p> <pre><code>2011-05-05 13:17:40.885 myapp[27033:207] -[NSCFNumber count]: unrecognized selector sent to instance 0x5d14eb0 2011-05-05 13:17:40.887 myapp[27033:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFNumber count]: unrecognized selector sent to instance 0x5d14eb0' *** Call stack at first throw: ( 0 CoreFoundation 0x014065a9 __exceptionPreprocess + 185 1 libobjc.A.dylib 0x0155a313 objc_exception_throw + 44 2 CoreFoundation 0x014080bb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187 3 CoreFoundation 0x01377966 ___forwarding___ + 966 4 CoreFoundation 0x01377522 _CF_forwarding_prep_0 + 50 5 CoreFoundation 0x013b7c3b -[NSSet intersectsSet:] + 59 6 Foundation 0x00c3f4fb NSKeyValueWillChangeBySetMutation + 422 7 Foundation 0x00c0416d NSKeyValueWillChange + 400 8 Foundation 0x00c3f34d -[NSObject(NSKeyValueObserverNotification) willChangeValueForKey:withSetMutation:usingObjects:] + 315 9 CoreData 0x01172bd0 -[NSManagedObject willChangeValueForKey:withSetMutation:usingObjects:] + 112 10 myapp 0x0004fd48 -[B addUpdatedObject:] + 168 11 CoreData 0x011729f2 -[NSManagedObject(_NSInternalMethods) _includeObject:intoPropertyWithKey:andIndex:] + 98 12 CoreData 0x01169301 -[NSManagedObject(_NSInternalMethods) _didChangeValue:forRelationship:named:withInverse:] + 497 13 Foundation 0x00c051e4 NSKeyValueNotifyObserver + 361 14 Foundation 0x00c04ca6 NSKeyValueDidChange + 384 15 Foundation 0x00beb3e2 -[NSObject(NSKeyValueObserverNotification) didChangeValueForKey:] + 123 16 CoreData 0x01166adb _PF_ManagedObject_DidChangeValueForKeyIndex + 171 17 CoreData 0x01165de9 _sharedIMPL_setvfk_core + 313 18 CoreData 0x01173997 _svfk_11 + 39 </code></pre> <p>(Yes, <em>B</em> has the method <code>addUpdatedObject</code>defined.) </p> <p>For further background, the list of A:s are shown in a <code>UITableView</code> backed by a <code>NSFetchedResultsController</code>. </p> <p>The strangest thing is, IMHO, that it's perfectly possible to add a new A (with B as creator) with the inverse relationship without it leading to a crash, while adding the same B as updater to that same A leads to a crash. </p> <p>However, when I remove the inverse relationships, everything works as expected. </p> <p><img src="https://i.stack.imgur.com/rmHBe.png" alt="Without inverse relationships"></p> <p>I can add the same B as A:s creator and updater without any problems, and the app works as it should, except for the build-time warnings from CoreData:</p> <pre><code>A.creator should have an inverse A.updater should have an inverse </code></pre> <p>So, is there any CoreData guru out there that can explain why the first case breaks? </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload