I have serious problems since I migrated my core data logic to RKManagedObjectStore. I setup a NSFetchedResultsController with the context set to [NSManagedObject managedObjectContext] within the main thread in the view controller:
assert([NSThread isMainThread]);
NSManagedObjectContext* context = [NSManagedObject managedObjectContext];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:[Item fetchRequest] managedObjectContext:context sectionNameKeyPath:nil cacheName:@"Master"];
I insert objects in the context like this:
Item* item = [Item object];
item.name = @"Foo";
[[RKObjectManager sharedManager].objectStore save];
But the fetched results controller doesn't get notified of the changes. Thus I registered a notification manually:
[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
NSLog(@"Context changed");
[self.fetchedResultsController performFetch:nil];
[self.tableView reloadData];
}];
This should really not be necessary I think, since RKManagedObjectStore merges changes across different contexts. Second, for deleting the Item object I tried
[item deleteEntity];
This produced an error saying that the object cannot be deleted within another context. This is obviously true, but WHY the hell is the context not the same instance for the Main Thread? I call the following also inside the view controller just before deleting en entity:
assert([NSThread isMainThread]);
NSManagedObjectContext* sameContext1 = [NSManagedObject managedObjectContext];
NSManagedObjectContext* sameContext2 = self.fetchedResultsController.managedObjectContext;
assert(sameContext1 == sameContext2); //FAILS
Looking at RKManagedObjectStore's managedObjectContext getter Implementation which is called when using [NSManagedObject managedObjectContext], the same instance per thread should be returned:
-(NSManagedObjectContext*)managedObjectContext {
NSMutableDictionary* threadDictionary = [[NSThread currentThread] threadDictionary];
NSManagedObjectContext* backgroundThreadContext = [threadDictionary objectForKey:RKManagedObjectStoreThreadDictionaryContextKey];
...
}
I finally tracked it down that nasty bug after hours of debugging. The problem is that RKObjectManager
holds a reference to RKManagedObjectStore
. But somehow when using ARC that reference is not kept in the [RKObjectManager sharedManager]
instance and is being deallocated. That causes flushing of the thread local cache. Therefore managed object context merging is not working because on every access a new managed context is created. The fix is easy. Just keep a strong reference to the RKManagedObjectStore
in your App Delegate and you're done.
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