Use MagicalRecord with another existing context in RestKit
-
22-06-2021 - |
Question
I want to keep using my current RestKit while use MagicRecord for rest of fetches and updates. I want Restkit's MOC send updates to MagicRecord's default context. If I understand right, this is what I am doing. Is this ok?
NSManagedObjectContext* context = [[RKObjectManager sharedManager].objectStore managedObjectContextForCurrentThread];
[MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreNamed:[XDBStore storeName]];
[context setParentContext:[NSManagedObjectContext MR_defaultContext]];
Maybe another way to do it, but still not sure.
NSPersistentStoreCoordinator *coordinator = [[[RKObjectManager sharedManager] objectStore] persistentStoreCoordinator];
[NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:coordinator];
[NSManagedObjectContext MR_initializeDefaultContextWithCoordinator:coordinator];
Anyone had same issue before?
EDIT 1
I tried the @casademora's suggestion #1 to set default context, but got this error.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Can only use -performBlockAndWait: on an NSManagedObjectContext that was created with a queue.'
EDIT 2
I found a hack. First, open up the setter for default context at magicalrecord. Next, change the concurrency type for RestKit store so its context can be used at magicalrecord.
NSManagedObjectContext+MagicalRecord.h
+ (void) MR_setDefaultContext:(NSManagedObjectContext *)moc;
+ (void) MR_setRootSavingContext:(NSManagedObjectContext *)context;
RKManagedObjectStore.m
NSManagedObjectContext *managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
Then setup MagicalRecord like this:
NSManagedObjectContext* context = [[RKObjectManager sharedManager].objectStore managedObjectContextForCurrentThread];
[NSManagedObjectContext MR_setRootSavingContext:context];
NSManagedObjectContext *defaultContext = [NSManagedObjectContext MR_newMainQueueContext];
[defaultContext setParentContext:context];
[NSManagedObjectContext MR_setDefaultContext:defaultContext];
Solution
There is an example project available showcasing how to use RestKit with MagicalRecord @ https://github.com/blakewatters/RKMagicalRecord
OTHER TIPS
To summarise Blake's solution
Use a class extension to expose access to MagicalRecord's private setter methods
@interface NSManagedObjectContext ()
+ (void)MR_setRootSavingContext:(NSManagedObjectContext *)context;
+ (void)MR_setDefaultContext:(NSManagedObjectContext *)moc;
@end
Do core data setup first, then this
[NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:managedObjectStore.persistentStoreCoordinator];
[NSManagedObjectContext MR_setRootSavingContext:managedObjectStore.persistentStoreManagedObjectContext];
[NSManagedObjectContext MR_setDefaultContext:managedObjectStore.mainQueueManagedObjectContext];
There are two ways to achieve this:
1) Get the main context from RestKit, and set that as the default context:
NSManagedObjectContext *rkContext = ...; //You'll have to figure this part out
[NSManagedObjectContext MR_setDefaultContext:rkContext];
2) For every fetch you do, just specify the context:
NSMangedObjectContext *rkContext = ...; //again, I don't know where to get this in restkit
[MyEntity MR_findAllInContext:rkContext]; // <- This will use the RestKit context