Whoa
Whoa

Reputation: 1334

RestKit, NSFetchedResultsController, and deleting orphaned objects

I have RestKit set up & working properly with an API and Core Data, using an NSFetchedResultsController to display the information. All is working well, except for the deleting of local objects once they have been deleted on the server. I've tried to follow the RestKit documentation for deleting orphaned objects with RKObjectManager, but it doesn't seem to be working. Here's what I have, any insight would be great:

Object Mapping

+ (RKMapping *)locationMapping{
//Create object map
//Same mapping as object mapping, but to NSManagedObjects
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Location" inManagedObjectStore:[RKManagedObjectStore defaultStore]];

//Map the identical json / object properties
[mapping addAttributeMappingsFromArray:@[@"name", @"city", @"zip", @"recipient", @"street", @"state"]];

//Map the non-identical properties (left side = json, right side = NSObject)
[mapping addAttributeMappingsFromDictionary:@{
                                              @"id": @"locationID",
                                              @"user_id":@"userID"
                                              }];

[mapping setIdentificationAttributes:@[@"locationID"]];

[mapping addRelationshipMappingWithSourceKeyPath:@"user" mapping:[self userMapping]];
[mapping addConnectionForRelationship:@"user" connectedBy:@"userID"];

RKObjectManager *rkObjectManager = [RKObjectManager sharedManager];

//Delete any orphaned objects
[rkObjectManager addFetchRequestBlock:^NSFetchRequest *(NSURL *URL) {
    RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:@"/api/v1/:userID/locations"];
    NSDictionary *argsDict = nil;
    if ([pathMatcher matchesPath:[URL relativePath] tokenizeQueryStrings:NO parsedArguments:&argsDict]) {
        NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Location"];
        return fetchRequest;
    }
    return nil;
}];


return mapping;
}

Note - the addFetchRequestBlock is not executing when the mapping is run, or an API call is made

Pulling the data

+(void)loadUserLocations{
//Don't try to load if there is no logged in user
if(![self getCurrentUser])return;

//Create an index of successful status codes
NSIndexSet *statusCodeSet = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);

//Pull location mapping from Mapping Provider
RKMapping *mapping = [MappingProvider locationMapping];

//Determine how rest kit will deal with the response. Specific to API calls
RKResponseDescriptor *rkResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping
                                                                                          method:RKRequestMethodGET
                                                                                     pathPattern:@"/api/v1/users/:userID/locations"
                                                                                         keyPath:nil
                                                                                     statusCodes:statusCodeSet];

//Create the URL & response
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@/users/%@/locations", [Statics baseURL], [self getCurrentUser].userID]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];

//Create the operation. Pass through AFHttp (more options) or NSURL
//When the request hits the path pattern (in this case, /locations),
//it will use the mapping to create the appropriate items
RKManagedObjectRequestOperation *operation = [[RKManagedObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[rkResponseDescriptor]];


//Set the cache
operation.managedObjectCache = [RKManagedObjectStore defaultStore].managedObjectCache;
operation.managedObjectContext = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext;

[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {

} failure:^(RKObjectRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
    NSLog(@"Response: %@", operation.HTTPRequestOperation.responseString);
}];

[operation start];
}

Setting up the NSFetchedResultsController

-(NSFetchedResultsController*)fetchedResultsController{
if (_fetchedResultsController != nil) {
    return _fetchedResultsController;
}

NSFetchRequest *fetchRequest =   [[RKManagedObjectStore defaultStore].managedObjectModel fetchRequestFromTemplateWithName:@"userLocations" substitutionVariables:@{@"USERID":[User getCurrentUser].userID}];

//Sort the request
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
                          initWithKey:@"locationID" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

[fetchRequest setFetchBatchSize:20];

//Create a new controller and set it to the VC
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                                                    managedObjectContext:self.mainMOC sectionNameKeyPath:nil
                                                                               cacheName:@"Root"];
NSLog(@"%@",fetchRequest);

self.fetchedResultsController.delegate = self;

return self.fetchedResultsController;
}

Could this be a cache issue? Or am I improperly setting things up?

Upvotes: 0

Views: 927

Answers (1)

Wain
Wain

Reputation: 119031

The path pattern /api/v1/:userID/locations in your fetch request block doesn't match your GET request.

But your main problem is that for the fetch request block to be used the object manager needs to be running the request. As it is you're creating the request and operation explicitly and executing. You should create and configure the object manager fully and use it to make the request (which should be less code for you to write too).

Upvotes: 1

Related Questions