I came across intriguing behaviour when using NSManagedObjectContext's performBlock:
with notification center.
From the main UI thread I trigger asynchronous data download (using NSURLConnection's connectionWithRequest:
). When data arrive the following delegate method is called:
- (void)downloadCompleted:(NSData *)data
{
NSArray *new_data = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
self.backgroundObjectContext = [[NSManagedObjectContext alloc]
initWithConcurrencyType:NSPrivateQueueConcurrencyType];
self.backgroundObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator;
[self.backgroundObjectContext performBlockAndWait:^{
[self saveToCoreData:new_data];
}];
}
The savetoCoreData:
method is simply saving new data to the background context:
- (void)saveToCoreData:(NSArray*)questionsArray
{
for (NSDictionary *questionDictionaryObject in questionsArray) {
Question *newQuestion = [NSEntityDescription
insertNewObjectForEntityForName:@"Question"
inManagedObjectContext:self.backgroundObjectContext];
newQuestion.content = [questionDictionaryObject objectForKey:@"content"];
}
NSError *savingError = nil;
[self.backgroundObjectContext save:&savingError];
}
In the view controller, in viewDidLoad
I add observer to the notification center:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextChanged:)
name:NSManagedObjectContextDidSaveNotification
object:nil];
And then in the contexChanged:
I merge the background context with the main context so that my NSFetchedResultsController's delegate methods are called where my view can be updated:
- (void)contextChanged:(NSNotification*)notification
{
if ([notification object] == self.managedObjectContext) return;
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}
It all seems to work well, but there is one thing that bothers me. When in downloadCompleted:
method I use performBlock:
instead of performBlockAndWait:
the notification seems to be delayed. It takes noticeable (around 5s) amount of time from the moment the background thread does save:
till the moment NSFetchedResultsController calls its delegate. When I use performBlockAndWait:
I do not observe any visible delay - the delegate is called as fast as if I called saveToCoreData:
inside _dispatch_async_
.
Does anyone saw that before and know if this is normal or am I abusing something?
[self.managedObjectContext performBlockAndWait:...]
– Dan ShellyconnectionWithRequest:
calls the delegate methods on "(...) the thread that started the asynchronous load operation for the associated NSURLConnection object." This can be easily observed by checking[NSThread isMainThread]
. – everyday productive