title: How to store nested JSON object into Core Data using RestKit
body: <p>I’m trying to implement what I believe to be a pretty simple use case, but I’m not sure how to correctly go about it.</p>
  
  <p>When a particular screen loads in my app, I need to call a webservice which returns a nested JSON object, then parse all the data and save into a series of Core Data managed objects. Whenever the user goes leaves and goes back to that screen, I want to replace all the data currently in my Core Data store with new data coming back from the server.</p>
  
  <p>That’s the high level overview. Seems pretty simple.</p>
  
  <p><code>setupRestKit</code> is called on app load: </p>
  
  <pre><code>+ (void)setupRestKit
  {
      RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:BASE_URL]];
      [RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:@"application/vnd.collection+json"];
  
      NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"Mobile" ofType:@"momd"]];
      NSManagedObjectModel *managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
      RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
  
      [managedObjectStore createPersistentStoreCoordinator];
  
      NSString *documentPath = [NIAppDelegate applicationDocumentsDirectory].relativePath;
      NSError *error;
      [managedObjectStore addSQLitePersistentStoreAtPath:[NSString stringWithFormat:@"%@/Mobile.sqlite", documentPath]
                                  fromSeedDatabaseAtPath:nil
                                       withConfiguration:nil
                                                 options:nil
                                                   error:&amp;error];
  
      [managedObjectStore createManagedObjectContexts];
  
      manager.managedObjectStore = managedObjectStore;
  
      NSArray *rkClasses = [self allNIRestKitClasses];
      NSArray *descriptors = [self allDescriptorsFromRKClasses:rkClasses];
  
      [manager addResponseDescriptorsFromArray:descriptors];
  }
  </code></pre>
  
  <p>The <code>NSArray *descriptors</code> on line 25 is populated with an array of descriptors, which includes the following returned descriptor object:</p>
  
  <pre><code>+ (RKResponseDescriptor *)getDescriptor
  {
      RKManagedObjectStore *store = [RKObjectManager sharedManager].managedObjectStore;
  
      RKEntityMapping *scheduleMapping = [RKEntityMapping mappingForEntityForName:@"Schedule" inManagedObjectStore:store];
      [scheduleMapping addAttributeMappingsFromDictionary:@{@"version": @"version",
                                                        @"href": @"href"}];
  
      RKEntityMapping *scheduleItemMapping = [RKEntityMapping mappingForEntityForName:@"ScheduleItem" inManagedObjectStore:store];
      [scheduleItemMapping addAttributeMappingsFromDictionary:@{@"href": @"href"}];
  
      RKEntityMapping *scheduleDataMapping = [RKEntityMapping mappingForEntityForName:@"ScheduleData" inManagedObjectStore:store];
      [scheduleDataMapping addAttributeMappingsFromDictionary:@{@"AllCurricConfirmed": @"allCurricConfirmed",
                                                                @"EndDateTime": @"endDateTime",
                                                                @"EventLocation": @"eventLocation",
                                                                @"Notes": @"notes",
                                                                @"RecordID": @"recordID",
                                                                @"ScheduleType": @"scheduleType",
                                                                @"StartDateTime": @"startDateTime",
                                                                @"Title": @"title"}];
  
      RKEntityMapping *scheduleLinkMapping = [RKEntityMapping mappingForEntityForName:@"ScheduleLink" inManagedObjectStore:store];
      [scheduleLinkMapping addAttributeMappingsFromDictionary:@{@"rel": @"rel",
                                                                @"href": @"href"}];
  
      RKRelationshipMapping *scheduleLinksInScheduleItem = [RKRelationshipMapping relationshipMappingFromKeyPath:@"link"
                                                                                                       toKeyPath:@"scheduleLinks"
                                                                                                     withMapping:scheduleLinkMapping];
      [scheduleItemMapping addPropertyMapping:scheduleLinksInScheduleItem];
  
      RKRelationshipMapping *scheduleDatasInScheduleItem = [RKRelationshipMapping relationshipMappingFromKeyPath:@"data"
                                                                                                   toKeyPath:@"scheduleDatas"
                                                                                                 withMapping:scheduleDataMapping];
      [scheduleItemMapping addPropertyMapping:scheduleDatasInScheduleItem];
  
      RKRelationshipMapping *scheduleItemsInSchedule = [RKRelationshipMapping relationshipMappingFromKeyPath:@"items"
                                                                                                   toKeyPath:@"scheduleItems"
                                                                                                 withMapping:scheduleItemMapping];
      [scheduleMapping addPropertyMapping:scheduleItemsInSchedule];
  
      NSIndexSet *scheduleStatusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
      RKResponseDescriptor *scheduleDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:scheduleMapping
                                                                                           method:RKRequestMethodGET
                                                                                      pathPattern:nil
                                                                                          keyPath:@"collection"
                                                                                      statusCodes:scheduleStatusCodes];
  
      return scheduleDescriptor;
  }
  </code></pre>
  
  <p>Those descriptors and relationships completely encompass my nested JSON object, and I believe them to work correctly.</p>
  
  <p>My question, I guess, is with how RestKit and Core Data work together. I’m relatively new to both of these technologies. The following snippet describes what my ViewController is doing to get data from the webservice:</p>
  
  <pre><code>// ViewController.m
  - (void)getData
  {
      [SVProgressHUD showWithStatus:@"Downloading Schedule"];
  
      [NIRestKitSchedule getScheduleWithBlock:^(BOOL valid) {
          if (valid) {
              // get the data from Core Data (because I assume that RestKit has saved everything into it already?)
              NSManagedObjectContext *mainContext = RKObjectManager.sharedManager.managedObjectStore.mainQueueManagedObjectContext;
              NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:@"Schedule"];
              NSArray *schedule = [mainContext executeFetchRequest:fetch error:nil];
  
              // TODO: and do stuff with it
  
              [SVProgressHUD dismiss];
          } else {
              [SVProgressHUD showErrorWithStatus:@"Could not get Schedule"];
          }
      }];
  }
  
  // NIRestKitSchedule.m
  + (void)getScheduleWithBlock:(void (^)(BOOL))valid
  {
      [self deleteEntity:@"Schedule"];
  
      NSURL *scheduleUrl = [RKObjectManager sharedManager].baseURL;
  
      scheduleUrl = [scheduleUrl URLByAppendingPathComponent:SCHEDULE_ENDPOINT];
  
      scheduleUrl = [scheduleUrl URLByAppendingDefaultParameters];
      [[RKObjectManager sharedManager] getObjectsAtPath:[scheduleUrl absoluteString]
                                             parameters:nil
                                                success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
                                                    valid(YES);
                                                }
                                                failure:^(RKObjectRequestOperation *operation, NSError *error) {
                                                    valid(NO);
                                                }];
  
  }
  
  + (void)deleteEntity:(NSString *)entityName
  {
      NSManagedObjectContext *mainContext = [RKObjectManager sharedManager].managedObjectStore.mainQueueManagedObjectContext;
  
      NSFetchRequest *fetchObjects = [[NSFetchRequest alloc] init];
      [fetchObjects setEntity:[NSEntityDescription entityForName:entityName inManagedObjectContext:mainContext]];
      [fetchObjects setIncludesPropertyValues:NO];
  
      NSError *error = nil;
      NSArray *objects = [mainContext executeFetchRequest:fetchObjects error:&amp;error];
  
      for (NSManagedObject *object in objects) {
          [mainContext deleteObject:object];
      }
      NSError *saveError = nil;
      [mainContext save:&amp;saveError];
  }
  </code></pre>
  
  <p>Upon compiling the app and running for the first time, <code>schedule</code> in the last code snippet is correctly loaded with the nested array of data. But any subsequent calls to <code>getData</code> result in a Core Data “fault".</p>
  
  <p>Should I be calling <code>getObjectsAtPath:parameters:success:failure</code>? Which contexts should I be storing and deleting my Schedule data into and from? Can someone point me in the right direction? RestKit is kind of overwhelming me right now.</p>