I am having the following problem: I use RestKit to get objects form a REST Api. The object mapping works, which I can see from the RK Debugger Output. However, when I perform a fetch request afterwards, the result is empty. I am talking about NSManagedObjects. I have the following setup.
1: Restkit and Coredata stack initialization:
NSError *error;
NSURL *baseURL = [NSURL URLWithString:@"https://mfihost.us/gocoffee/api/V1/"];
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:baseURL];
[objectManager.HTTPClient setDefaultHeader:@"Token" value:[NSString stringWithFormat:@"%@",[FBSDKAccessToken currentAccessToken].tokenString]];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
objectManager.managedObjectStore = managedObjectStore;
//[RKObjectManager setSharedManager:objectManager];
[FetchRequests registerFetchRequests:objectManager];
[Descriptors registerDescriptors:objectManager];
[managedObjectStore createPersistentStoreCoordinator];
NSPersistentStore *persistentStore = [managedObjectStore addInMemoryPersistentStore:&error];
NSAssert(persistentStore, @"Failed to add inmemory store with error: %@", error);
[managedObjectStore createManagedObjectContexts];
managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
2: call to get objects from server and performing a fetch request afterwards:
[[RKObjectManager sharedManager]
postObject:nil path:@"/gocoffee/api/V1/login/IOS"
parameters:nil
success: ^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(@"Objects have been saved in core data.");
NSManagedObjectContext *managedObjCtx = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext;
// Shout* sh=[managedObjCtx insertNewObjectForEntityForName:@"Shout"];
// sh.inviterUserId=@"22223";
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Shout" inManagedObjectContext:managedObjCtx];
[fetchRequest setEntity:entity];
NSError *error = nil;
NSArray *result = [managedObjCtx executeFetchRequest:fetchRequest error:&error];
if (error) {
NSLog(@"Unable to execute fetch request.");
NSLog(@"%@, %@", error, error.localizedDescription);
} else {
NSLog(@"%@", result);
}
completionBlock();
}
failure: ^(RKObjectRequestOperation *operation, NSError *error) {
RKLogError(@"Load failed with error: %@", error);
}];
The fetch result is empty, although the server returns objects and these objects are properly mapped by using RKEntityMappings and the corresponding response descriptors. Confusingly, if I uncomment the two lines //Shout * .... (i.e. manually insert a managed oject into the context), then this object is fetched by the fetch request. Consequently, the fetch request should be working fine. I am searching for ages now what the problem might be. Could it be that I am calling on the wrong context or something ? By the way: core-data multi-threading debugging is enabled and does not show any error, i.e. no "AllThatIsLeftToUsIsHonor" error.
The corresponding route from the above example is:
[objectManager.router.routeSet
addRoute:[RKRoute routeWithName:@"loginAndOrSignup"
pathPattern:@"login/IOS"
method:RKRequestMethodPOST]
];
The descriptors look like (example):
[objectManager addResponseDescriptor:
[RKResponseDescriptor responseDescriptorWithMapping:[shoutMapping inverseMapping]
method:RKRequestMethodPOST
pathPattern: @"login/IOS"
keyPath:@"response.incomingshoutapplications"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)
]
];
Shout mapping is as follows:
RKEntityMapping *shoutMapping = [RKEntityMapping mappingForEntityForName:@"Shout" inManagedObjectStore:managedObjectStore];
shoutMapping.identificationAttributes = @[ @"id" ];
[shoutMapping addAttributeMappingsFromDictionary:@{
@"id" : @"id",
@"inviterUserId" : @"inviterUserId",
@"eventType" : @"eventType",
@"eventTime" : @"eventTime",
@"locationLat" : @"locationLat",
@"locationLng" : @"locationLng",
@"radius" : @"radius",
@"targetGender" : @"targetGender",
@"state" : @"state",
@"buddyOnly" : @"buddyOnly",
@"timeCreated" : @"timeCreated"
}
];
The "manager" ist the one from above, the managedObjectStore is manager.managedObjectStore All the mappings and descriptors are setup in another method that is calles by [Descriptors registerDescriptors:objectManager]; (see first block of code)
The problem is probably that you're using inverseMapping
. That is used mainly for request mapping, because it's a mapping that creates instances of NSMutableDictionary
, which isn't what you want.
So, what I expect is happening is that the response is mapped successfully, but to plain objects, not managed objects, and then you're throwing the result away.
Just change to
... responseDescriptorWithMapping:shoutMapping ...