herrtim
herrtim

Reputation: 2755

RESTKit - How to always replace all cached objects rather than updating?

I'd like to use RESTKit not in the default way, which as far as I understand, is to update the cached objects by looking at unique IDs and either adding objects to the cache when new IDs are found or purging objects from the cache when old IDs exist.

What I'd like to do instead is always fetch objects from a URL endpoint, set the cache with these new objects, removing all the previous existing cached objects. The thing is that my JSON doesn't have any unique IDs.

Is it possible to do this? I unsuccessfully tried removing the objects in the cache before calling for new objects. Before I try too many other things, I thought I'd ask here first if there is a standard way of doing this in RESTKit.

Thanks in advance!

Upvotes: 3

Views: 1747

Answers (2)

herrtim
herrtim

Reputation: 2755

As Wain said, the way to do this is to use a RKFetchRequestBlock. I'm not 100% sure what's going on in the section Fetch Request Blocks and Deleting Orphaned Objects RKManagedObjectRequestOperation, but in my case, all I needed to do was return a NSFetchRequest for each matched path. Since I have three endpoints in my app and three entities, I needed to have three separate pattern matching checks and return 3 unique NSFetchRequests. From what I understand, the manager will automatically consult the fetch request blocks and perform orphaned object cleanup if a NSFetchRequest is returned.

Here's my code:

RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:baseURL];

    // To perform local orphaned object cleanup
    [objectManager addFetchRequestBlock:^NSFetchRequest *(NSURL *URL) {

        RKPathMatcher *pathMatcherLeft = [RKPathMatcher pathMatcherWithPattern:@"/api/app/left.json"];
        BOOL matchLeft = [pathMatcherLeft matchesPath:[URL relativePath] tokenizeQueryStrings:NO parsedArguments:nil];
        RKPathMatcher *pathMatcherRight = [RKPathMatcher pathMatcherWithPattern:@"/api/app/right.json"];
        BOOL matchRight = [pathMatcherRight matchesPath:[URL relativePath] tokenizeQueryStrings:NO parsedArguments:nil];
        RKPathMatcher *pathMatcherCenter = [RKPathMatcher pathMatcherWithPattern:@"/api/app/center.json"];
        BOOL matchCenter = [pathMatcherCenter matchesPath:[URL relativePath] tokenizeQueryStrings:NO parsedArguments:nil];
        if (matchLeft) {
            NSLog(@"Pattern matched left.json!");
            NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"LeftViewItem"];
            return fetchRequest;
        }else if (matchRight) {
                NSLog(@"Pattern matched right.json!");
                NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"RightViewItem"];
                return fetchRequest;
        }else if (matchCenter) {
            NSLog(@"Pattern matched center.json!");
            NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"CenterViewItem"];
            return fetchRequest;
        }
        return nil;
    }];

Upvotes: 2

Wain
Wain

Reputation: 119031

Yes, you can. You wouldn't want to use unique ids anyway for what you describe (though it would work if you did, but you may be left with some old data in your updated objects).

Anyway, omit any unique id from your mapping and specify a fetch request block (section Fetch Request Blocks and Deleting Orphaned Objects) that simply fetches all of the instances of your entity (no predicate). This will cause RestKit to delete all of the old objects and save all new objects during the mapping.

Your test of deleting all of the objects before making the request should work so long as you update the correct context and save it correctly.

Upvotes: 3

Related Questions