5

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.

gpichler
  • 2,181
  • 2
  • 27
  • 52
  • You didn't set any parameters or values to the PFObject. You just specifice do where it's going and then pinned it. Add values or keys – soulshined Jan 15 '15 at 23:14
  • @soulshined thanks for your hint, I tried to shorten my answer and did a copy paste mistake. – gpichler Jan 16 '15 at 08:19

4 Answers4

1

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 :

Community
  • 1
  • 1
soulshined
  • 9,612
  • 5
  • 44
  • 79
  • thank you very much for your answer, I really appreciate your help. I had some time to update my whole answer and hopefully it's a little bit clearer now. I still have the same problem. – gpichler Jan 19 '15 at 19:02
  • @user1463853 do you have a typo in your newly revised question or is it a possible lead? [newContact saveEventually]; doesn't reference the PFObject your creating named *contact not *newContact. Instead do : `[contact saveEventually]; – soulshined Jan 23 '15 at 02:55
  • that was a typo in my question, I'm using the correct reference in my code. (fixed it in question) – gpichler Jan 23 '15 at 12:54
  • @user1463853 can you show everything related to setting the object please. How are you setting self.firstname & self.lastname and please show how you are setting kFirstnameKey kRelatedToUserKeyetc. – soulshined Jan 25 '15 at 03:10
  • I'm not sure if this is the problem, because if I'm using the app in online mode, all values are perfectly saved in the backend. It also does not work if I set a hardcoded string instead of referencing these properties. – gpichler Jan 25 '15 at 10:26
  • @user1463853 i've updated my answer - you should really consider a 'guaranteed' method (i.e, `saveInBackground`, `save:`) if it's essential information or as mentioned, check reachability first and _then_ act accordingly. – soulshined Jan 26 '15 at 02:21
  • if saveEventually is set to an object and before it gets a chance to go to the parse server how can you delete it ? Unpinning doesnt seem to work. – DogCoffee Apr 06 '15 at 06:15
1

It was a bug on the sdk.(1.6.2)

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

Franck
  • 8,939
  • 8
  • 39
  • 57
0

I had a similar problem, I actually found that removing or not calling [Parse enableLocalDatastore]; resulted in saveEventually performing as expected (using Parse 1.6.2). I had assumed [Parse enableLocalDatastore]; would be required for this to work.

Workshed
  • 236
  • 1
  • 8
0

This bug is now fixed in Parse version 1.6.3!

gpichler
  • 2,181
  • 2
  • 27
  • 52