0
votes

I am having trouble understanding how I go about caching and retrieving objects with Parse. I am trying to create a query, and cache the objects, then only retrieve cached objects, unless the user saves objects to PFObject, then I would like to use network to reload the data.

This is my attempt and how I am querying for PFObjects.

    //Gets the playlists from the desired user
    +(void)getPlaylistsForUser:(PFUser *)user withCompletion:(void(^)(NSMutableArray *playlists))completion
    {
        PFQuery *userQuery = [PFQuery queryWithClassName:@"Playlists"];
        userQuery.cachePolicy = kPFCachePolicyCacheElseNetwork;
        [userQuery whereKey:@"userId" equalTo:[user objectId]];
        [userQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
            if (!error){
                NSMutableArray *playlists = [[NSMutableArray alloc]init];
                playlists = [objects mutableCopy];
                    completion(playlists);
                }
        }];
    }

How would I go about notifying the query that there needs to be a network call instead of returning cached results?

EDIT: I managed to get the desired functionality with just a few lines of code.

//Gets the playlists from the desired user
+(void)getPlaylistsForUser:(PFUser *)user withCompletion:(void(^)(NSMutableArray *playlists))completion
{
    PFQuery *userQuery = [PFQuery queryWithClassName:@"Playlists"];
    [userQuery whereKey:@"userId" equalTo:[user objectId]];
    userQuery.cachePolicy = kPFCachePolicyCacheElseNetwork;
    [userQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (!error){
            NSMutableArray *playlists = [[NSMutableArray alloc]init];
            playlists = [objects mutableCopy];
                completion(playlists);
            }
    }];
}
+ (void)saveTrack:(NSDictionary *)track toPlaylist:(PFObject *)playlist withCompletion:(void(^)(BOOL success))completion
{
    [playlist addObject:track forKey:@"playlist"];
    [playlist saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
        if (error)
        {
            NSLog(@"Error creating/saving playlist");
        }
        else{
            PFUser *current = [PFUser currentUser];
            PFQuery *playlistQuery = [PFQuery queryWithClassName:@"Playlists"];
            [playlistQuery whereKey:@"userId" equalTo:[current objectId]];
            [playlistQuery clearCachedResult];

            completion((BOOL)YES);
        }
    }];
}

Essentially, I am just clearing the specific query's cached results when I need the query to reload data. And I am setting the query's cachePolicy to kPFCachePolicyCacheElseNetwork

Is this the best way to go about caching? Seems to be working as intended.

1

1 Answers

0
votes

Looks fine, but a little wordy. I would, instead, keep state for the cache policy if not the query itself...

@property (assign, nonatomic) PFCachePolicy cachePolicy;
// initialize this to kPFCachePolicyIgnoreCache (==0 so it will be by default)

// return a playlist query
+ (PFQuery *)playlistQueryForUser:(PFUser *)user {
    PFQuery *query = [PFQuery queryWithClassName:@"Playlists"];
    query.cachePolicy = self.cachePolicy;
    [query whereKey:@"userId" equalTo:[user objectId]];
    return query;
}

Now your code just needs a little change, and is a little better, imo, because it saves the clear cache operation and represents explicitly your intention with the cache. (see comments that say "diff here")...

//Gets the playlists from the desired user
+(void)getPlaylistsForUser:(PFUser *)user withCompletion:(void(^)(NSMutableArray *playlists))completion
{
    // diff here...
    PFQuery *query = [self playlistQueryForUser:user];
    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (!error){
            NSMutableArray *playlists = [[NSMutableArray alloc]init];
            playlists = [objects mutableCopy];
            completion(playlists);

            // diff here...
            self.cachePolicy = kPFCachePolicyCacheThenNetwork;
        }
    }];
}

+ (void)saveTrack:(NSDictionary *)track toPlaylist:(PFObject *)playlist withCompletion:(void(^)(BOOL success))completion
{
    [playlist addObject:track forKey:@"playlist"];
    [playlist saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
        if (error) {
            NSLog(@"Error creating/saving playlist");
        } else {
            // diff here: no need to rebuild the query, just change policy...  
            self.cachePolicy = kPFCachePolicyIgnoreCache;
            completion((BOOL)YES);
        }
    }];
}