I'm getting the following error:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Unable to perform mapping: No `managedObjectContext` assigned. (Mapping response.URL = https://www.someurl.com/lastrequest=2014-12-08T02%3A44%3A52Z)'
The app stops at the following line in RKResponseMapperOperation.m:
- (RKMappingResult *)performMappingWithObject:(id)sourceObject error:(NSError **)error
{
NSLog(@"managedObjectContext: %@, Source Object: %@ Error: %@", self.managedObjectContext, sourceObject, (*error).description);
NSAssert(self.managedObjectContext, @"Unable to perform mapping: No `managedObjectContext` assigned. (Mapping response.URL = %@)", self.response.URL);
....
I noticed that the above method was called 27 (this number varies) times prior to the app crashing. In each instance, NSManagedObjectContext was present i.e. the line below:
2014-12-07 18:44:48.721 MyApp[19011:3258405] managedObjectContext:managedObjectContext: <NSManagedObjectContext: 0x1701f5800>, Source Object: {
friends = (
);
} Error: (null)
However right before it crashed, the NSManagedObjectContext was null:
2014-12-07 18:44:53.454 MyApp[19011:3258404] managedObjectContext: (null), Source Object: {
friends = (
);
} Error: (null)
Since the app functions normally for a while before it crashes, I'm not sure how to address this. Any pointers would be greatly appreciated.
* EDIT *
In Appdelegaate. This method is called once in viewDidLoad when the User logs in.
- (RKManagedObjectStore *)managedObjectStore
{
if (!_managedObjectStore && [Persistence loggedIn])
{
NSError * error;
NSURL * modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"App" ofType:@"momd"]];
NSManagedObjectModel * managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
self.managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
[_managedObjectStore createPersistentStoreCoordinator];
NSArray * searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentPath = [searchPaths objectAtIndex:0];
NSString *dbName = [NSString stringWithFormat:@"%@App%@.sqlite", documentPath, [Persistence username]];
NSPersistentStore * persistentStore = [_managedObjectStore addSQLitePersistentStoreAtPath:dbName
fromSeedDatabaseAtPath:nil
withConfiguration:nil
options:[self optionsForSqliteStore]
error:&error];
NSAssert(persistentStore, @"Failed to add persistent store with error: %@", error);
NSLog(@"Path: %@", dbName);
if(!persistentStore)
{
NSLog(@"Failed to add persistent store: %@", error);
}
[_managedObjectStore createManagedObjectContexts];
self.managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:self.managedObjectStore.persistentStoreManagedObjectContext];
return self.managedObjectStore;
}
return _managedObjectStore;
}
- (id)optionsForSqliteStore
{
return @{
NSInferMappingModelAutomaticallyOption: @YES,
NSMigratePersistentStoresAutomaticallyOption: @YES
};
}
Creating MOC: For Core Data stack, I'm using the Default Core Data code in AppDelegate that's provided when the project is created in Xcode.
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
MOC Operation:
- (void)saveContext
{
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
Inside the App, the methods below are used to set, get, and clear ObjectManager:
- (void)refreshMOC
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
self.objectManager = [self getObjectManager];
self.objectManager.managedObjectStore = appDelegate.managedObjectStore;
self.objectManager.managedObjectStore.managedObjectCache = appDelegate.managedObjectStore.managedObjectCache;
self.managedObjectContext = self.objectManager.managedObjectStore.mainQueueManagedObjectContext;
}
- (RKObjectManager *)setupObjectManager
{
NSURL *baseURL = [NSURL URLWithString:kBaseURL];
AFHTTPClient *httpClient = [[AFHTTPClient alloc]initWithBaseURL:baseURL];
RKObjectManager *manager = [[RKObjectManager alloc]initWithHTTPClient:httpClient];
[manager.HTTPClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[manager setAcceptHeaderWithMIMEType:RKMIMETypeJSON];
[manager.HTTPClient setParameterEncoding:AFJSONParameterEncoding];
[RKMIMETypeSerialization registeredMIMETypes];
[RKObjectManager setSharedManager:manager];
return [RKObjectManager sharedManager];
}
- (RKObjectManager *)getObjectManager
{
self.objectManager = (!self.objectManager) ? [self setupObjectManager] : self.objectManager;
return self.objectManager;
}
- (RKObjectManager*)newObjectManager
{
[self clearRKObjectManager];
return [self getObjectManager];
}
- (void)clearRKObjectManager
{
if (self.objectManager)
{
self.objectManager = nil;
}
}