NSManagedObjectContext and executeBlock, changes in iOS 8?

I have an old project (running on iOS 7) with this simple code:

in AppDelegate I create managedObjectContext:

- (NSManagedObjectContext *)managedObjectContext {
    // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (!coordinator) {
        return nil;
    }
    _managedObjectContext = [[NSManagedObjectContext alloc] init];
    [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    return _managedObjectContext;
}

      

Then I perform an update operation in the view controller:

    [context performBlock:^{
        [context deleteObject:anObject];

        NSError *error = nil;
        if (![context save:&error])
        {
            NSLog(@"Error saving context");
        }
    }];

      

I'm sure this code worked correctly on iOS 7.0, but it fails when called performBlock:

on iOS 8 with this error:

Can only use -performBlockAndWait: on the NSManagedObjectContext that was created with the queue.

I can resolve the error by changing the init method of the NSManagedObjectContext instance as follows:

_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

      

But I don't understand why this behavior changed. In the NSManagedObjectContext documentation, you can read:

The consequence of this is that the context assumes that the default owner is the thread or queue that allocates it - this is determined by the thread that calls its init method.

So in my first example, using a simple call init

, the owner of the context queue is the main thread. The call performBlock:

was made on the main thread as well, so I don't understand why this error. Am I missing something or is this a bug in iOS 8?

+3


source to share


1 answer


The call -[NSManagedObjectContext init]

is just a wrapper around -[NSManagedObjectContext initWithConcurrencyType:]

with an argument NSConfinementConcurrencyType

. This will create an instance NSManagedObjectContext

that uses the legacy content constraint model that doesn't use a queue. Contexts created using init

or initWithConcurrencyType:

with a passed value NSConfinementConcurrencyType

are incompatible with the methods of the queue performBlock:

or performBlockAndWait:

.



Build your context with -[NSManagedObjectContext initWithConcurrencyType:]

and swipe either NSPrivateQueueConcurrencyType

or NSMainQueueConcurrencyType

if needed. The resulting context is compatible with performBlock:

and performBlockAndWait:

will use the queue constraint model that was introduced in iOS 5.

+1


source







All Articles