Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse saveEventually saves empty object

When I'm trying to save a PFObject without network connection it is successfully saved locally, whenever I start the app again with network connection, it seems that the object is going to be saved to the server, but all parameters are empty.

I'm doing the following procedure, first I create a PFObject with different values and call saveEventually. During these steps I do not have an internet connection (airplane mode is on), therefore it can't be saved to the server and was saved locally.

PFObject *contact = [PFObject objectWithClassName:@"Contact"];
[contact setObject:[PFUser currentUser] forKey:kRelatedToUserKey];
[contact setObject:self.firstname forKey:kFirstnameKey];
[contact setObject:self.lastname forKey:kLastnameKey];

[contact saveEventually];

Now, I'm closing the app and start it again, I'm loading my contacts like that. I'm getting back the correct object with all the correct value for firstname, lastname, etc.

PFQuery *postQuery = [PFQuery queryWithClassName:@"Contact"];
[postQuery whereKey:@"related_to_user" equalTo:[PFUser currentUser]];
[postQuery fromLocalDatastore];
[postQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
    if (!error) {
        // here I get back the correct object from local storage, with all values
    }
}];

Now, when I'm switching airplane mode off, it tries to save the object to the server, but all I can see in the backend is an objectId without any values.

enter image description here

Whereas the locally saved object has all the correct values.

like image 523
gpichler Avatar asked Oct 31 '22 11:10

gpichler


2 Answers

So what are you trying to do exactly? Here's how it reads:

Your querying 'Contact' class and once you query it and find an object by it's ID (an object you don't do anything with [PFObject *contact]) then you create a PFObject for a completely different Class?? You could circumvent all that if you simply just want to post a PFObject, but maybe you omitted other code that wasn't relevant to the question? But ok. To answer your question saveEventually works hand-in-hand with local data store, so you shouldn't have any issues, as you can see, it get's called, but your values aren't being saved like the objectID is. The objectID is created autonomously, that's why it gets saved and nothing else. I have literally tried to duplicate your error in every way possible but can't, it's your values, they are returning nil. I even used macros (it looks like thats what your setting your keys as), emulated airplane mode etc. To verify, query your pinned object and see what it returns. Additionally, it's best when you do a callback to try to include an if statement or switch case that explicity defines it respectively for better practice :

{
    if (succeeded) {
         debt.parseID = newDebt.objectId;
    }];
}];

Furthermore, be careful about putting essential tasks in the success block because an important element of saveEventually is that if it doesn't complete before the app is terminated and if the object is still in memory, it will try again, but if the object is no longer in memory it will try again the next run-time, but WITHOUT the success block.

Troubleshoot your property values (self.contact | self.amount | self.incomingDebt) how are you defining these


We've come a long ways from the original post, so in an effort to try and bring it back, the real and only issue here is saveEventually.

Saves this object to the server at some unspecified time in the future, even if Parse is currently inaccessible.

The main intent of saveEventually :

Use this when you may not have a solid network connection, and don’t need to know when the save completes

If more than 10MB of data is waiting to be sent, subsequent calls to will cause old saves to be silently discarded until the connection can be re-established, and the queued objects can be saved.

You have no control over when this gets called. Additionally, saving eventually caches the data on the local disk until it can be successfully uploaded, so pinning the same object is redundant. Saving eventually, if you think about it, is a local datastore of it's own, it's stores them on the local disk until internet is available (local datastore)

You have two ways that could circumvent this. Local datastore is a core-data-esque feature enabling users to forego NSFRC with a simple one-liner code pin/pinInBackground:. You could simply pin the objects and when you know there is internet again unpin and save to your backend. Alternatively you could do it the other way, call reachability immediately, and if there is no internet pin: the object, else saveInBackground: first. Or simply take advantage of their caching policies.


REFERENCES :

  • saveEventually : API Class Reference
  • Caching Policies : Documentation
like image 184
soulshined Avatar answered Nov 12 '22 17:11

soulshined


It was a bug on the sdk.(1.6.2)

Submitted here: https://developers.facebook.com/bugs/1554492594835537/

like image 21
Franck Avatar answered Nov 12 '22 16:11

Franck