Yoko
Yoko

Reputation: 803

Parse pinned objects not updating

I have the following code to update my objects that have changed on the server:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

[PFCloud callFunctionInBackground:@"getAllData" withParameters:@{@"LastUpdate": [self getLastSyncDate], @"Scan": @"NO"} block:^(NSArray *result, NSError *error){        
    if (!error) {
        for (int x = 0; x < result.count; x++) {
            PFObject *object = [result objectAtIndex:x];
            [object unpinInBackgroundWithName:object.parseClassName block:^(BOOL succeeded, NSError *error){
                if (!error) {
                    if ([object[@"deleted"] boolValue] != YES) {
                        [object pinInBackgroundWithName:object.parseClassName block:^(BOOL succeeded, NSError *error){
                            if (x == result.count - 1) {
                                [self performSelector:@selector(reloadTableView) withObject:nil afterDelay:0.3];
                            }
                        }];
                    }
                }
            }];
        }
        [defaults setObject:[NSDate date] forKey:@"LastSynced"];
        [defaults synchronize];
    }
    [self reloadTableView];
}];

But my objects are not updating. Calling a PFQuery from the local datastore shows me the old versions.

Any idea?

Upvotes: 1

Views: 158

Answers (1)

Ryan Kreager
Ryan Kreager

Reputation: 3581

It looks like you have a bunch of background functions nested in each other, and this is causing a racing error.

Here's the order of operations for your code:

  1. Get the data
  2. Iterate through each item for updates and save changes in the background (this is key)
  3. Synchronize
  4. Reload

Just getting to the end of the iteration does not mean that all the saves are complete - You need to wait until all the saves from step 2 are complete before you continue with steps 3 and 4.

A suggested order of operations:

  1. Get the data
  2. Set a global with the number of objects, and another global with the number that have been updated (starts at 0)
  3. Iterate through each item for updates and check with a function to see if all the updates are complete, i.e. do your two global equal each other. **Only if all updates are complete do you sync and reload

Something like this:

//Declare these two globally
int total; 
int complete;


complete = 0;
*defaults = [NSUserDefaults standardUserDefaults];
[PFCloud callFunctionInBackground:@"getAllData" withParameters:@{@"LastUpdate": [self getLastSyncDate], @"Scan": @"NO"} block:^(NSArray *result, NSError *error){        
    if (!error) {
        total = result.count;
        for (int x = 0; x < result.count; x++) {
            PFObject *object = [result objectAtIndex:x];
            [object unpinInBackgroundWithName:object.parseClassName block:^(BOOL succeeded, NSError *error){
                if (!error) {
                    if ([object[@"deleted"] boolValue] != YES) {
                        [object pinInBackgroundWithName:object.parseClassName block:^(BOOL succeeded, NSError *error){
                            self.total++;
                            [self updateCompleteCheck];
                        }];
                    }
                }
            }];
        }
    }
}];

-(void)updateCompleteCheck 
{
    if(total == complete) {
        //Only when this is done do you know, for certain, the update is really complete
        [defaults setObject:[NSDate date] forKey:@"LastSynced"];
        [defaults synchronize];
        [self reloadTableView];
    }
}

Upvotes: 1

Related Questions