PFInstallation and adding a pointer to a PFUser - ios

I am trying to get to grips with Parse and build a simple chat app. For my login and signup code I have this snippet:
PFInstallation *installation = [PFInstallation currentInstallation];
installation[#"user"] = [PFUser currentUser];
[installation saveInBackground];
This code connects a PFInstallation to a PFUser so a push can be sent by querying a username.
When the app loads I first check to see if there is already a user logged in:
if ([PFUser currentUser]) {
[self performSegueWithIdentifier:#"showFriends" sender:nil];
}
if a user is already logged in the show friends view controller is loaded. Do I need to set the installation again in this code to match the user? i.e.
if ([PFUser currentUser]) {
PFInstallation *installation = [PFInstallation currentInstallation];
[installation[#"user"] = [PFUser currentUser];
[installation saveInBackground];
[self performSegueWithIdentifier:#"showFriends" sender:nil];
}
Or is there no need because the user is already logged in? Am I right in thinking that the installation file is UNIQUE and only created once, matching the device to the push service so nothing really changes in that file unless I want to update the PFUser field I added?
thanks

if a user is already logged in the show friends view controller is loaded. Do I need to set the installation again in this code to match the user?
No. Installations and User classes act independently, but in your case since you set a relation then they can act together as well. Since you already set it in application didFinishLaunchingWithOptions: that device has uniquely identified its installation with the token you've provided (device token) so you don't have to call it again.
A User session is different. If you want the User to be logged in you will have to present the login VC somewhere, since it won't be there the first launch.
Am I right in thinking that the installation file is UNIQUE and only created once, matching the device to the push service so nothing really changes in that file unless I want to update the PFUser field I added? thanks
Yes. That's pretty accurate. Just don't get confused. PFUser currentUser is not the same as PFInstallation currentInstallation anyone can sign on to a device but the app can only be installed once on a device making the installation unique. Not users.

Related

Where can I view my PFUser objects in the Parse Data Browser?

I'm getting to know Parse and am already having a tough problem.
I'm working with the User Login flow. I need to be able to delete the User object I've just created. Problem is, on the Dashboard, I only have the Installation data table.
I realized I wasn't explicitly saving this user object, although locally (on iOS) I could log in with the currentUser object credentials. So I thought I'd remove the install from the simulator and try again (hey, since my data wasn't on the dashboard.)
Now I tried re-installing the app, using the same username/pass, and Parse SDK is telling me these are already taken!
So the question is, where is this User, and how do I completely remove the data so I can start over again?
2015-10-15 16:37:29.999 ParseApp[21428:2003831] [Error]: username myUserName already taken (Code: 202, Version: 1.8.5)
This doesn't solve the problem, but is kind of like a workaround for testing purposes. I made a method:
- (IBAction)pressedDeleteSelf:(id)sender
{
[[PFUser currentUser] deleteInBackgroundWithBlock:^(BOOL succeeded, NSError * _Nullable error) {
if (succeeded) {
[PFUser logOut];
[self performSegueWithIdentifier:#"unwindSignedOut" sender:self];
}
}];
}
Which then allows me to re-create a user with the same credentials. I still have no idea why the PFUser table does not show up in the Dashboard.
Oh myyy... how silly do I feel. With all these different tutorials I've been running, apparently I had been doing all this stuff using the wrong AppID and Client Key. A rookie mistake, but hopefully someone else doesn't have to trip on this.
To be clear, solution is to make sure your App ID and Client key in the Parse dashboard match what you call in code:
// Initialize Parse.
[Parse setApplicationId:PARSE_APP_ID
clientKey:PARSE_CLIENT_KEY];
Embarrassed...

Parse error codes 209 and -34018

I have spent several hours learning user management on Parse, thinking it would be easy considering it's been an established service for so long.
There is poor documentation around 'automatic user' and sessions.
I am trying to build an App that allows the user to exist anonymously (using [PFUser enableAutomaticUser]), before they decide to sign up.
Registration Steps:
Gather user details from the UI
Log out current automatic user and wait for success
Upon success create a user object using [PFUser user] and assign values
Call signUpInBackgroundWithBlock on the new user instance
I sometimes get the following errors (yes, only sometimes), when doing the above.
[Error]: PFKeychainStore failed to get object for key 'currentUser', with error: -34018
[Error]: invalid session token (Code: 209, Version: 1.7.0)
I also end up with a dirty database, because I don't know how to delete the automatic user that was previously created. I tried keeping the object id of the old user around and using deleteEventually but that didn't work?
Any advice on how you would go about achieving this would be great.
Take a look at this issue with parse on iOS: https://github.com/ParsePlatform/Parse-SDK-iOS-OSX/issues/437.
I believe this was an issue in iOS and is now fixed
Actually, this is a bug of keychain, you can search it at github.
Github 34018 issues
A few months ago, some apple's staff came our company to give us a course, after course,we asked this question, they also did't give us a solution
I've solved this problem by using the following:
PFUser *user = [PFUser currentUser];
[user refreshInBackgroundWithBlock:^(PFObject *object, NSError *error) {
if (!error) {
NSLog(#"Succesfully refreshed the current user.");
} else {
NSLog(#"Failed to refresh the current user with error %#", error);
}
}];
It seems that [PFUser currentUser] returns an invalid session token which is causing the 209 and -34018 errors. This is only an issue when the current user is an anonymous user.

Anonymous user persists in database after successful log in

Using Parse.com and anonymous users enabled (w/ automatic creation) - this is the scenario:
Start the app - anonymous user #1 gets created on database
Sign up with username & password - anonymous user #1 gets converted to regular user
Delete app - reinstall & start up - anonymous user #2 gets created
This time do not sign up but rather log in - log in successful, but anonymous user #2 persists in cloud.
How do I make anonymous user #2 from step 4 to go away (completely, I don't want junk in the database)?
As long as the user is otherwise logged out and you therefore know that currentUser either contains nil or the anonymous user object, you should be able to store the anonymous user object then delete that user object upon successful login, ex:
PFUser *anonymousUser;
if ([PFUser currentUser] != nil) {
anonymousUser = [PFUser currentUser];
}
[PFUser logInWithUsernameInBackground:emailString password:passwordString block:^(PFUser* user, NSError* error){
if (user) {
if (anonymousUser)
[anonymousUser deleteInBackground];
}
}

Can player2 sends a notification to player1 using Parse, from the device?

Is it possible to send a push notification from a device (player2), to another device (player1), when player2 has finished, using the "user" identifier in Parse? It would be like this :
player 1 plays, and sends his score
player 2 plays, checks if player1 has finished, if he has, player2 sends a notification to player1 using the "user" identifier of player1 ?
Push notifications are sent to devices, not users. Devices are tracked via the installation table (PFInstallation object). You need to add a column to your installations table in Parse so that it tracks the PFUser that is currently associated with that installation (device). Then you can send a push message that targets installations where the current user is "player 1"
Example -
Whenever your user "logs in" to your game, you need to update the associated installation -
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
currentInstallation[#"currentPlayer"]=[PFUser currentUser];
[PFInstallation saveInBackground];
Then to send a message
PFQUery *pushQuery=[PFInstallation query];
[pushQuery whereKey:#"currentPlayer" equalTo:self.opponent]; // self.opponent is a PFUser
[PFPush sendPushMessageToQueryInBackground:pushQuery
withMessage:#"It's your turn"];

Sending push notification to a particular user in Parse

I'm having a devil of a time trying to do what seems like the simplest possible thing: I want to send a push notification to a particular user, and I already have the PFUser object for that user.
I tried the following:
// 'recipient' is the PFUser
PFQuery *pushQuery = [PFInstallation query];
[pushQuery whereKey:#"owner" equalTo:recipient];
I also tried replacing "owner" with "user". In both cases, the push seems to succeed (no error reported) but the device never gets the notification.
I know that the device is properly registered and logged in because I can send pushe notifications from the Parse web console.
What's the right way to do this?
Thanks,
Frank
I ended up using a nested query to get this.
var userQuery = new Parse.Query(Parse.User);
userQuery.equalTo('objectId', recipient);
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.matchesQuery('user', userQuery);
Ok, it turns out that this is a two-step process.
When the user logs in or creates an account, you have to put a "user" property in PFInstallation:
[[PFInstallation currentInstallation] setObject:[PFUser currentUser] forKey:#"user"];
[[PFInstallation currentInstallation] saveEventually];
Only then will the query work.
That seems like a lot of manual work for something that the Parse server should know without my having to set it up.

Resources