Note that there are some explanatory texts on larger screens.

plurals
  1. PONSSortDescriptor of NSFetchRequest not working after context save
    primarykey
    data
    text
    <p>I'm doing operations in a GCD dispatch queue on a NSManagedObjectContext defined like this:</p> <pre><code>- (NSManagedObjectContext *)backgroundContext { if (backgroundContext == nil) { self.backgroundContext = [NSManagedObjectContext MR_contextThatNotifiesDefaultContextOnMainThread]; } return backgroundContext; } </code></pre> <p><code>MR_contextThatNotifiesDefaultContextOnMainThread</code> is a method from <a href="https://github.com/magicalpanda/MagicalRecord" rel="nofollow">MagicalRecord</a>:</p> <pre><code>NSManagedObjectContext *context = [[self alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; [context setParentContext:[NSManagedObjectContext MR_defaultContext]]; return context; </code></pre> <p>After fetching my objects and giving them the correct queue position i log them and the order is correct. However, the second log seems to be completely random, the sort descriptor clearly isn't working.</p> <p>I have narrowed down the Problem to <code>[self.backgroundContext save:&amp;error]</code>. After saving the background context sort descriptors are broken.</p> <pre><code>dispatch_group_async(backgroundGroup, backgroundQueue, ^{ // ... for (FooObject *obj in fetchedObjects) { // ... obj.queuePosition = [NSNumber numberWithInteger:newQueuePosition++]; } NSFetchRequest *f = [NSFetchRequest fetchRequestWithEntityName:[FooObject entityName]]; f.predicate = [NSPredicate predicateWithFormat:@"queuePosition &gt; 0"]; f.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"queuePosition" ascending:YES]]; NSArray *queuedObjects = [self.backgroundContext executeFetchRequest:f error:nil]; for (FooObject *obj in queuedObjects) { DLog(@"%@ %@", obj.queuePosition, obj.title); } if ([self.backgroundContext hasChanges]) { DLog(@"Changes"); NSError *error = nil; if ([self.backgroundContext save:&amp;error] == NO) { DLog(@"Error: %@", error); } } queuedObjects = [self.backgroundContext executeFetchRequest:f error:nil]; for (FooObject *obj in queuedObjects) { DLog(@"%@ %@", obj.queuePosition, obj.title); } }); </code></pre> <p>I've got no idea why the sort descriptor isn't working, any Core Data experts want to help out?</p> <p><strong>Update:</strong></p> <p>The problem does not occur on iOS 4. I think the reason is somewhere in the difference between thread isolation and private queue modes. MagicalRecord automatically uses the new concurrency pattern which seems to behave differently.</p> <p><strong>Update 2:</strong></p> <p>The problem has been solved by adding a save of the background context:</p> <pre><code>if ([[NSManagedObjectContext MR_contextForCurrentThread] hasChanges]) { DLog(@"Changes"); NSError *error = nil; if ([[NSManagedObjectContext MR_contextForCurrentThread] save:&amp;error] == NO) { DLog(@"Error: %@", error); } else { NSManagedObjectContext *parent = [NSManagedObjectContext MR_contextForCurrentThread].parentContext; [parent performBlockAndWait:^{ NSError *error = nil; if ([parent save:&amp;error] == NO) { DLog(@"Error saving parent context: %@", error); } }]; } } </code></pre> <p><strong>Update 3:</strong></p> <p>MagicalRecord offers a method to recursively save a context, now my code looks like this:</p> <pre><code>if ([[NSManagedObjectContext MR_contextForCurrentThread] hasChanges]) { DLog(@"Changes"); [[NSManagedObjectContext MR_contextForCurrentThread] MR_saveWithErrorHandler:^(NSError *error) { DLog(@"Error saving context: %@", error); }]; } </code></pre> <p>Shame on me for not using it in the first place...</p> <p>However, I don't know <em>why</em> this helps and would love to get an explanation.</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.
    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