Entities:
Relationships:
In the Playlist entity, I have not exposed the playlistItem relationship / set. Instead I have a transient undefined attribute called "videos," which is an array of Video entities generated by sorting the set of Playlist Items. There is not a relationship between Playlist and Video entities.
I'm having problems when saving a modified Playlist instance in the Managed Object Context.
From playlist.m (NSManagedObject subclass):
- (BOOL)validatePlaylistItems:(NSSet **)playlistItems error:(NSError **)outError
{
NSArray *currentVideos = [self videos];
NSArray *persistedVideos = [self videosFromPlaylistItems];
if ([currentVideos isEqual:persistedVideos]) {
return YES;
}
NSManagedObjectContext *context = [self managedObjectContext];
for (FHPlaylistItem *pi in *playlistItems) {
[context deleteObject:pi];
}
NSArray *videos = [self primitiveVideos];
NSUInteger count = [videos count];
for (int i = 0; i < count; i++) {
FHPlaylistItem *pi = [FHPlaylistItem playlistItemWithVideo:[videos objectAtIndex:i]
forIndex:i
insertIntoManagedObjectContext:[self managedObjectContext]];
[self addPlaylistItemsObject:pi];
[pi setPlaylist:self];
}
return YES;
}
What I'm trying to accomplish here is only update the set of Playlist Items when the MOC needs to save, as you can see the operation is expensive - O(N * 2). During the first run of the app, the MOC saves just fine. However, subsequent changes to the videos attribute yields in Core Data spewing a bunch of errors:
Core Data: annotation: repairing missing delete propagation for to-many relationship playlistItems on object <FHPlaylist: 0x6c27eb0> (entity: Playlist; id: 0x6c26d40 <x-coredata://BCB69D8E-8393-4A2A-AF5D-0AA1872CE2B4/Playlist/p19> ; data: {
accountID = 0;
lastFetched = "2012-03-31 20:05:08 +0000";
name = Featured;
playlistID = 1441335931001;
playlistItems = (
"0x6c34be0 <x-coredata:///PlaylistItem/t9EAFBC87-5E16-4053-984F-881CCD9C1F0B2>",
"0x6c34320 <x-coredata://BCB69D8E-8393-4A2A-AF5D-0AA1872CE2B4/PlaylistItem/p16>",
"0x6c310c0 <x-coredata:///PlaylistItem/t9EAFBC87-5E16-4053-984F-881CCD9C1F0B3>",
"0x6c35570 <x-coredata:///PlaylistItem/t9EAFBC87-5E16-4053-984F-881CCD9C1F0B5>",
"0x6c34ca0 <x-coredata:///PlaylistItem/t9EAFBC87-5E16-4053-984F-881CCD9C1F0B6>",
"0x6c34310 <x-coredata://BCB69D8E-8393-4A2A-AF5D-0AA1872CE2B4/PlaylistItem/p8>",
"0x6c28a90 <x-coredata:///PlaylistItem/t9EAFBC87-5E16-4053-984F-881CCD9C1F0B4>",
"0x6c34350 <x-coredata://BCB69D8E-8393-4A2A-AF5D-0AA1872CE2B4/PlaylistItem/p29>",
"0x6c34220 <x-coredata://BCB69D8E-8393-4A2A-AF5D-0AA1872CE2B4/PlaylistItem/p2>",
"0x6c34330 <x-coredata://BCB69D8E-8393-4A2A-AF5D-0AA1872CE2B4/PlaylistItem/p20>",
"(...and 1 more...)"
);
playlistType = 0;
referenceID = OKFFeaturedPlaylist;
shortDescrip = "This is so descriptive! OMG!";
thumbnailURL = nil;
videos = "(...not nil..)";
}) with bad fault 0x6c34320 <x-coredata://BCB69D8E-8393-4A2A-AF5D-0AA1872CE2B4/PlaylistItem/p16>
Core Data: annotation: repairing missing delete propagation for to-many relationship playlistItems on object <FHPlaylist: 0x6c27eb0> (entity: Playlist; id: 0x6c26d40 <x-coredata://BCB69D8E-8393-4A2A-AF5D-0AA1872CE2B4/Playlist/p19> ; data: {
accountID = 0;
lastFetched = "2012-03-31 20:05:08 +0000";
name = Featured;
playlistID = 1441335931001;
playlistItems = (
"0x6c34be0 <x-coredata:///PlaylistItem/t9EAFBC87-5E16-4053-984F-881CCD9C1F0B2>",
"0x6c310c0 <x-coredata:///PlaylistItem/t9EAFBC87-5E16-4053-984F-881CCD9C1F0B3>",
"0x6c35570 <x-coredata:///PlaylistItem/t9EAFBC87-5E16-4053-984F-881CCD9C1F0B5>",
"0x6c34ca0 <x-coredata:///PlaylistItem/t9EAFBC87-5E16-4053-984F-881CCD9C1F0B6>",
"0x6c34310 <x-coredata://BCB69D8E-8393-4A2A-AF5D-0AA1872CE2B4/PlaylistItem/p8>",
"0x6c28a90 <x-coredata:///PlaylistItem/t9EAFBC87-5E16-4053-984F-881CCD9C1F0B4>",
"0x6c34350 <x-coredata://BCB69D8E-8393-4A2A-AF5D-0AA1872CE2B4/PlaylistItem/p29>",
"0x6c34220 <x-coredata://BCB69D8E-8393-4A2A-AF5D-0AA1872CE2B4/PlaylistItem/p2>",
"0x6c34330 <x-coredata://BCB69D8E-8393-4A2A-AF5D-0AA1872CE2B4/PlaylistItem/p20>",
"0x6c34340 <x-coredata://BCB69D8E-8393-4A2A-AF5D-0AA1872CE2B4/PlaylistItem/p27>"
);
playlistType = 0;
referenceID = OKFFeaturedPlaylist;
shortDescrip = "This is so descriptive! OMG!";
thumbnailURL = nil;
videos = "(...not nil..)";
}) with bad fault 0x6c34310 <x-coredata://BCB69D8E-8393-4A2A-AF5D-0AA1872CE2B4/PlaylistItem/p8>
Etc. Etc. Etc.
It seems to be the problem lies with the delete rule. The complaint is with a "missing delete propagation," so it seems nullify is the wrong choice. But, why is it wrong? This doesn't make sense to me. The wording of the cascade delete rule in Apple's Core Data Programming Guide makes it seem like I'm going to delete the Video and Playlist objects if I set Playlist Item's delete rule to cascade.
Cascade - Delete the objects at the destination of the relationship
Furthermore, if I set the relationship from Playlist Item to video & playlist to nil in the fast enumeration loop, Core Data doesn't complain about having to repair the missing delete propagation.
for (FHPlaylistItem *pi in *playlistItems) {
[pi setVideo:nil];
[pi setPlaylist:nil];
[context deleteObject:pi];
}
EDIT: Nope, nil'ing the relationships manually didn't work in all situations. (Maybe no surprise?)
Inverse relationships enable Core Data to propagate change in both directions when an instance of either the source or destination type changes. Every relationship must have an inverse. When creating relationships in the Graph editor, you add inverse relationships between entities in a single step.
Setting the Delete Rule to Protect prevents deleting records of the main Entity while there are associated records in the related Entity. This behavior is ensured by a database constraint created on the reference attribute.
Overview. Core Data provides a set of classes that collaboratively support your app's model layer: An instance of NSManagedObjectModel describes your app's types, including their properties and relationships. An instance of NSManagedObjectContext tracks changes to instances of your app's types.
Try if [[self managedObjectContext] processPendingChanges] after your delete block will solve the strange messages for you.
It seems Core Data will get confused in some situations when you go on altering the managed object context in the same run loop cycle and some of the involved objects had relationships to the deleted objects.
Regards,
sven.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With