I am using RestKit 0.2.x with Core Data and following the standard tutorials, ie:
- Create Core Data model and use
mogenerator
to make code - Instantiate object manager with base URL
- Create managed object context and persistent store
- Create entity mappings for all entities returned by my web service
- Create response descriptors for all web service endpoints and entities
- Add response descriptor to object manager
Everything seems to be "working" just fine ... I can call
[[RKObjectManager sharedManager] getObjectsAtPath:_requestPath parameters:_requestParameters success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
[self requestSuccess];
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
[self requestError:error];
}];
... all day long, and I then I keep handling with (as shown in the tutorials)
- (void)requestSuccess {
NSManagedObjectContext *managedObjectContext = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext;
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:_entityName];
fetchRequest.sortDescriptors = @[_defaultSortDescriptor];
NSError *error = nil;
requestData = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
[_delegate handleRequestSuccess:self withData:requestData];
//[self cleanupRequestBeforeSuccessWithData:requestData];
[self completeRequest];
}
Now the problem is that at least by default, RestKit+CoreData actually persists your GET'ted objects to its own persistence store, or something like that. I'll explain the "cleanupRequest..." in a moment.
That kind of defeats the purpose of trying to allow the users to specify parameters at the level of the web service client, because all of the objects seem to end up in the same place anyway.
For instance, let's say I have a method /api/endpoint?queryString
and I call it with two different sets of parameters:
[[RKObjectManager sharedManager] getObjectsAtPath:@"/api/endpoint" parameters:PARAMS_ONE success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
[self requestSuccess];
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
[self requestError:error];
}];
[[RKObjectManager sharedManager] getObjectsAtPath:@"/api/endpoint" parameters:PARAMS_TWO success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
[self requestSuccess];
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
[self requestError:error];
}];
If I then blindly follow the tutorials about how to retrieve my objects, my callbacks are then identical!
NSManagedObjectContext *managedObjectContext = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext;
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"EndpointDataTransferObject"];
fetchRequest.sortDescriptors = @["endpointDataTransferObjectID"];
NSError *error = nil;
requestData = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
The result, of course, is that the my delegate
gets sent (pseudocode) requestData WHERE PARAMS_ONE
on the first call, and then requestData WHERE PARAMS_ONE UNION requestData WHERE PARAMS_TWO
on the second call.
Now all I really want is to be able to conduct the NSFetchRequest
on only those items mapped from the web service. I think this is a totally reasonable expectation, so clearly I am missing something because whoever wrote this library is much more clever than I.
For instance, if I could somehow get an NSArray
of all the objects from the two parameters it provides in the success
block (RKRequestRequestOperation *o, RKMappingResult *m)
- and if I can, please tell me how!!! - then my problem would be solved, and I could enjoy the caching without having to worry about whether my filters are being ignored.
What I do not want to do, however, is this:
- Call
getObjectsAtPath: parameters: success: failure:
withparameters
and/orpath
representing a sort of "server-side" predicate - On success, create a
NSFetchRequest
and a client-side predicate that mirrors my server-side predicate
This approach seems really really dumb, and yet, I don't know any better. But I refuse to do that. It is error-prone, redundant, and potentially resource-intensive.
So instead, I've opted to add a little method cleanupRequestBeforeSuccessWithData
at the end of my success
callback before calling completion
:
- (void)cleanupRequestBeforeSuccessWithData:(NSArray *)managedObjects {
NSManagedObjectContext *managedObjectContext = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext;
for (NSManagedObject *o in managedObjects) {
[managedObjectContext deleteObject:o];
}
NSError *error = nil;
[managedObjectContext save:&error];
}
This is ugly but it sure gets the job done. Now it totally empties the cache, but I'd rather have to make requests over and over again than to form "server-side" predicates with URL's and then form client-side NSPredicate
s.
What am I missing about how this is supposed to work? Clearly, I'm missing something big.
Aucun commentaire:
Enregistrer un commentaire