Parse.com can't get correct username from Parse - ios

I am trying to implement Facebook auth with Parse SDK as described in officialy manual.
But instead of real name I am getting some token when calling [PFUser currentUser]
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
if ([PFUser currentUser] && [PFFacebookUtils isLinkedWithUser:[PFUser currentUser]]) {
NSLog(#"USER == %# == IS ALREADY LINKED WITH FACEBOOK", [PFUser currentUser]);
}
}
NSLOG shows me this: USER == Op2Qz1RxiwR1zflsSzCVR538A == IS ALREADY LINKED WITH FACEBOOK
What could be the issue?

In your code you are telling it to log the entire user object. This will probably log something like a unique I'd or something.
If you want the name then you should use...
[PFUser currentUser].userName
Or some other property.
It doesnt know which part of the user to log unless you actually tell it which part you want to log.

Related

PFUser currentUser returns null after a few days

I'm seeing a strange problem with what appear to be invalid Parse User sessions in my app. I currently use Facebook logins in conjunction with Parse to handle new users in my app.
Using the boilerplate code from Parse tutorials here after two days or so a call to [PFUser currentUser] returns null and my users are asked to login again.
To try to determine if it's related to Parse or Facebook I did the following by attempting to login with a valid Facebook Session when the [PFuser CurrentUser] returns null and it always seems to work.
This makes me think it's not the Facebook session but somehow that the Parse session gets corrupted or returns something strange from time to time. I'm sure I'm not logging out as my logout method is user driven and not called anywhere else in code.
Here's what I'm doing for authorization:
-(void)authorizeAndSaveUser{
//Check to see if we already have a valid PFUser to avoid authenticating again:
if(![PFUser currentUser]){
//*Patch - occasionally the [PFUser CurrentUser] returns null when we have a logged in user.
//My work around for this is to login with the Facebook Token if we have one
if([FBSDKAccessToken currentAccessToken]){ //<- This always succeeds after the user has been created!
// Log In (create/update currentUser) with FBSDKAccessToken
[PFFacebookUtils logInInBackgroundWithAccessToken:[FBSDKAccessToken currentAccessToken]
block:^(PFUser *user, NSError *error) {
if (!user) {
NSLog(#"Uh oh. There was an error logging in with saved FB access token.");
} else {
NSLog(#"Successful login with saved FB access token.");
}
}];
} else { // We have never logged in before so start creating a new user
//Ask for permissions
NSArray *permissionsArray = #[#"public_profile", #"email"];
// Login PFUser using Facebook
[PFFacebookUtils logInInBackgroundWithReadPermissions:permissionsArray block:^(PFUser *user, NSError *error){
if(!error){
if (!user) { //Case where the user cancelled the login
NSLog(#"Uh oh. The user cancelled the Facebook login.");
//The no error case - simply a cancelled login
} else if (user.isNew) { //Net new user
NSLog(#"New User signed up and logged in through Facebook!");
//We have permissions so query Facebook and Write this Data to our App.
[self writeFacebookUserDetailsToParse];
} else { //Returning User
NSLog(#"Existing User logged in through Facebook!");
//We have permissions so query Facebook and Write this Data to our App in order to update profile photos etc.
[self writeFacebookUserDetailsToParse];
}
} else { //The error case
NSLog(#"Uh oh. An error occurred: %#", error);
}
}];
}
}
}
Can anyone see anything obvious or offer any advice? Although not a constant issue it's enough of a pain that every user will encounter a popup to "Re-Login" at least once a week or so...
Thanks in advance,
Andrew
Seems that this was fixed by our friends at Parse using Framework 1.9.0. See the change-log here: https://www.parse.com/docs/downloads
"Fixed currentUser not restoring authentication when loaded from disk."
I'll confirm if I see this again
Andrew

PFUser currentUser returns nil

I'm using Parse SDK, login and signup are working perfectly : [PFUser currentUser] is returning the current user.
But after restarting app, [PFUser currentUser] is returning nil.
Why is the application not persisting the session ?
Login code (from parse.com) I'm using :
[PFUser logInWithUsernameInBackground:self.username.text password:self.password.text
block:^(PFUser *user, NSError *error) {
if (user) {
// Do stuff after successful login.
} else {
// The login failed. Check error to see why.
}
}];
EDIT 2: Create new project, it works. I don't know how and why, but it works.
EDIT: There is no logoutin the whole project
It looks like you are calling .logout somewhere, in which case the app will return nil for [PFUser currentUser].
The current user will persist from session to session if you do not automatically log out the user.
PFUser *currentUser = [PFUser currentUser];
if (currentUser) {
//save the installation
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
currentInstallation[#"installationUser"] = [[PFUser currentUser]objectId];
// here we add a column to the installation table and store the current user’s ID
// this way we can target specific users later
// while we’re at it, this is a good place to reset our app’s badge count
// you have to do this locally as well as on the parse server by updating
// the PFInstallation object
}

Pulling User Information from Parse Database

I am using Parse as my backend for my app. Once the user logs into their account I am trying to get the next view to say "Welcome, (First Name)" at the top. However, I cannot seem to figure out how to accomplish this even using Parse's online documents. Their site directed me here for further assistance. I have tried using their query feature, but could not figure it out. In other words, I am trying to pull the current logged in user's first name, from the database and display it once logged in.
Current code:
PFQuery *query = [PFUser query];
[query whereKey:#"firstName" equalTo:currentUser]; // find user's first name
NSArray *firstName = [query findObjects];
Previous code:
PFUser *currentUser = [PFUser currentUser];
if (currentUser) {
// do stuff with the user
Welcome.text = [NSString stringWithFormat:#"Welcome,", currentUser];
Your overcomplicating things.
You don't have to execute a query every time the view loads, instead you should put this in a plist or NSUserDefaults as not to use an API request simply to display the current users name.
However, you can do the following to the current users username :
if ([PFUser currentUser]) {
Welcome.text = [NSString stringWithFormat:#"Welcome, %#", [PFUser currentUser].username];
}
First of all you should check if you actually sign-up and/or logged into Parse with this kind of function:
[PFUser signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
}];
[PFUser logInWithUsernameInBackground:#"My username" password:#"My password" block:^(PFUser *validUser, NSError *error) {
}];
Check this link: https://parse.com/docs/ios_guide#users-signup/iOS
After you did this, whenever you you want to retrieve your user information,
[PFUser currentUser] is the right way to call some information:
Say for example you want to retrieve the objectId you can get it like this:
NSString *str = [PFUser currentUser].objectId;
Or say you want to set a custom value like this:
NSString *str = #"My custom object";
[PFUser setObject:str forKey:#"MyCustomObject"];
[PFUser saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
}];
Than you retrieve it like this:
NSString *str = [PFUser objectForKey:#"MyCustomObject"];
You should really check the documentation and example by Parse that are really well explained ! ;)
(Here are some tutorials/Examples by Parse: https://parse.com/tutorials)
How is the transition from your login to your main view set up? Are they both two different controllers?
If so, you should look into NSNotificationCenter...
In your MainViewController, implement
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(loadObjects)
name:#"loginFinished"
object:nil];
And loadObjects will be
- (void)loadObjects
{
Welcome.text = [NSString stringWithFormat:#"Welcome %#", [[PFUser currentUser] objectForKey:"userNameField"]];
}
* You need to parse the PFUser object to access its fields. Its just a dictionary so supply it a key 'username' or whatever, and you receive a value 'myusername'. *
Then in your LoginViewController, within your [PFUser logInWithUsernameInBackground:password:block
Implement this
[PFUser logInWithUsernameInBackground:#"My username" password:#"My password" block:^(PFUser *validUser, NSError *error) {
if (!error) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"loginFinished" object:nil];
}
}];
But this is basically how you should setup your login->main flow. Learn NSNotifications, Delegation, and maybe KVO... Learning these will make you a understand how data can be passed around in the iOS/Mac environment.
Heres an analogy for all of them:
NSNotification: A teacher(NSNotification poster) announces a test to all his students(NSNotification observer), or at least the one's who are currently in class, students missing class aren't observing.
Delegate: A student finishes a test and informs the professor(delegate).
KVO: A student(KVO poster) completes a question and raises their hand where the teacher or even other students could be KVOs (key-value observers) and act on their action.

Parse Login users without Facebook details in Data Browser

I am using [PFFacebookUtils loginWithPermissions] to let user log into Facebook in an iOS app. There is no other option for users to log-in. In the completion block I am calling [FBRequestConnection startForMeWithCompletionHandler]. In the completion block of second call I store the data obtained into the [PFUser currentUser] object (like username, email). The data browser in Parse dashboard shows empty data in email and other info received from Facebook for some of the users. I have proper conditional checks to see if the API calls are returning any errors.
This the code. There are many users with no FBID, Email and corrupted Username in Parse databrowser.
[PFFacebookUtils logInWithPermissions:nil block:^(PFUser *user, NSError *error) {
if (!user) {
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:#"Facebook error" message:#"To use you Facebook account with this app, open Settings > Facebook and make sure this app is turned on." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
} else {
[FBRequestConnection startForMeWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if (!error) {
[[PFUser currentUser] setObject:result[#"id"] forKey:kPFUser_FBID];
[[PFUser currentUser] setObject:result[#"name"] forKey:kPFUser_Username];
[[PFUser currentUser] setObject:result[#"email"] forKey:kPFUser_Email];
[[PFUser currentUser] saveInBackground];
}
}];
}
}];
It looks like the block is not entering the second piece of code(i.e it is getting error from FBRequestConnection method.
Please help!
I figured what was the issue here. I was calling
[PFFacebookUtils loginWithPermissions]
with nil permissions and was trying to access email address of the user. Parse was crashing when a null value was being entered in currentUser object.
Just replaced nil with #"email" permission.
Thanks for your help.
Are you remembering to save the current user after you finish setting the properties? That's an easy thing to forget.
UPDATE:
Add an else block to log any possible error returned from the Facebook call.
Also try changing your saveInBackground to saveInBackgroundWithBlock: and check for any errors, if the data isn't showing up in the Parse Data Browser that should always be the first thing you check.

Check is Parse user is already linked to facebook or twitter

I have set up a few Parse users, I have a button that they can click to link to fb or twitter. I want to check if they are already linked so I can have an alertview which tells the user they are already linked.
Any thoughts?
Parse provides a set of utils for this kind of thing, one part of which is:
+ (BOOL)isLinkedWithUser:(PFUser *)user
You can use PFQuery for this:
id loggedUser = ...; // Get your facebook/twitter user info after clicking login
PFQuery *query = [PFUser query];
[query whereKey:#"email" equalTo:loggedUser[#"email"]];
[query countObjectsInBackgroundWithBlock:^(int number, NSError *error) {
if(number > 0) {
// The user already exists
} else {
// No user exists with the email
}
}];
Source: Parse.com

Resources