Sending push notification to a particular user in Parse - ios

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.

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...

How to send push notification to specific user in Parse? [duplicate]

I have successfully setup parse push notifications and in my installation table I have both an installation, and device token. What I'm really trying to do is send a push notification to certain users, rather than certain devices. How do I bing the installations table to the uses table, so that I can make a query by users and get back a deviceid to push to
From https://parse.com/docs/push_guide#top/iOS, section "Using Advanced Targeting".
You can even create relationships between your Installation objects
and other classes saved on Parse. To associate a PFInstallation with a
particular user, for example, you can simply store the current user on
the PFInstallation.
// Associate the device with a user
PFInstallation *installation = [PFInstallation currentInstallation];
installation[#"user"] = [PFUser currentUser];
[installation saveInBackground];
Now you can create a query on the installation table, where "user" is the user you want to send a push notification to.
Finally, use that query when constructing the push object.
Example in Objective-C (adjust accordingly, if you're sending the push in some other language):
PFQuery *pushQuery = [PFInstallation query];
[pushQuery whereKey:#"user" equalTo:someUser]; // where some user is the user object that is to receive a push notification
PFPush *push = [[PFPush alloc] init];
[push setQuery:pushQuery];
[push setMessage:#"Hi there!"];
[push sendPushInBackground];

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.

PFInstallation and adding a pointer to a PFUser

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.

parse.com clarification of ACL (object not found for update)

I got the error "Error: object not found for update (Code: 101, Version: 1.2.9)"
I was told that this error "is typically returned when the current user does not have permission to write to the object in question."
Please help me make sure I understand ACL. I have the following code in my delegate:
PFACL *defaultACL = [PFACL ACL];
[defaultACL setPublicReadAccess:YES];
[PFACL setDefaultACL:defaultACL withAccessForCurrentUser:YES];
(1) So does that mean that for any PFObject I create during the current session, only the current user will be able to make changes to that object, unless I specify through a session of the current user other users who are allowed write access?
(2) Which I would do using the following code (from parse documentation)?
PFObject *groupMessage = [PFObject objectWithClassName:#"Message"];
PFACL *groupACL = [PFACL ACL];
// userList is an NSArray with the users we are sending this message to.
for (PFUser *user in userList) {
[groupACL setReadAccess:YES forUser:user];
[groupACL setWriteAccess:YES forUser:user];
}
groupMessage.ACL = groupACL;
[groupMessage saveInBackground];
(3) Now suppose I have a brand new PFUser whom I want to be able to edit an existing PFObject during his current session, but who is not included in the ACL for that existing object. How can I enable that user to edit the object? Would I have to use cloud code to add him to the ACL list? A code example would be appreciated.
Thank you.
Yes, the ACL you listed gives the current user write access and global read access. With this ACL, you'd need to explicitly decide who else should have write access.
It sounds like you're looking for the sort of dynamic group evaluation that a role offers you. If you give write permission to a role object, for example an admins role, then all object's permissions will be affected (without additional API calls) when you add or remove users to the role.
Using createWithoutData to set the referenced object helped me to solve this problem.
myObject.put("item", ParseObject.createWithoutData(<SUB CLASS>.class, <Your object item>));
myObject.saveInBackground();

Resources