Below is my code for phone number verification. First we query to check if user already exists; if so, I want to log in with that user. If not, I create a new PFUser.
- (IBAction)confirmButtonTapped:(id)sender
{
// Check to see if a valid phone number is entered
if ([self.phoneNumberTextField.text hasPrefix:#"+56"] && self.phoneNumberTextField.text.length == 12){
self.phoneNumber = [self phoneNumberWithoutSpaces:self.phoneNumberTextField.text];
// Check if phone number is already assigned to a Parse user
PFQuery *phoneNumberQuery = [PFUser query];
[phoneNumberQuery whereKey:#"phoneNumber" equalTo:self.phoneNumber];
[phoneNumberQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error){
if (!error){
if (objects.count > 0){
// Move on to main tab bar and log in with user found
PFUser *user = [objects objectAtIndex:0];
[PFUser logInWithUsernameInBackground:user.username password:user.password block:^(PFUser *user, NSError *error){
if (!error){
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:YES] forKey:#"recoverUser"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:self.phoneNumber, #"phoneNumber", nil];
[PFCloud callFunctionInBackground:#"sendVerificationCode" withParameters:dict block:^(id object, NSError *error){
if (error){
NSLog(#"Error calling cloud function: %#", error.localizedDescription);
}
}];
[self performSegueWithIdentifier:#"confirmNumberSegue" sender:self];
} else {
NSLog(#"Error logging in: %#", error.localizedDescription);
[[[UIAlertView alloc] initWithTitle:#"Connection Failed" message:#"Please try again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}
}];
} else {
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:NO] forKey:#"recoverUser"];
[[NSUserDefaults standardUserDefaults] synchronize];
//Create new Parse user
[self createNewUser];
}
} else {
NSLog(#"Error fetching user object: %#", error.localizedDescription);
[[[UIAlertView alloc] initWithTitle:#"Connection Failed" message:#"Please try again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}
}];
} else {
[[[UIAlertView alloc] initWithTitle:#"Invalid Phone Number" message:#"Please enter a valid phone number." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}
}
I am getting a Parse error when trying to log in (Code: 201) Missing user password.
Related
I have a problem.
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
UIImage* image = [info objectForKey:UIImagePickerControllerOriginalImage];
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
[self dismissViewControllerAnimated:YES completion:^{
if (image == nil){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Try again !" message:#"Please try again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
[self presentViewController:self.imagePicker animated:NO completion:nil];
}else{
NSData *fileData;
NSString *fileName;
NSString *fileType;
fileData = UIImagePNGRepresentation(image);
fileName = #"profilePic.png";
fileType = #"Image";
PFFile *file = [PFFile fileWithName:fileName data:fileData];
[file saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"An error occurred!"
message:[NSString stringWithFormat:#"Please try sending your message again. %#",error.userInfo]
delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}else{
[[PFUser currentUser]setObject:file forKey:#"profilePic"];
[[PFUser currentUser] saveInBackgroundWithBlock:^(BOOL succeed, NSError* error){
if (!error) {
NSLog(#"New profile pic loaded.");
[self.activity stopAnimating];
[self.reloadPicBtn setHidden:NO];
}else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Try again !" message:#"Please try again. Failed to load your new profile pic :(" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
}
}];
}
}];
}
}];
}
Well, reloadPicBtn is shown, but if I call a function which reloads a picture, It fails. And when I try to understand WTF is going on using NSLog it logs out a string. So code has been executed. But there is no result on screen. The function is the same which is called in viewDidLoad. But it works when it is called from viewDidLoad. And when it is called again there is no result.
That reload function:
- (void) loadProfilePic{
PFQuery* query = [PFUser query];
[query getObjectInBackgroundWithId:[PFUser currentUser].objectId block:^(PFObject* object, NSError* error){
if(!error){
PFFile* imageFile = object[#"profilePic"];
[imageFile getDataInBackgroundWithBlock:^(NSData* data, NSError* error){
if (!error) {
self.activity.hidden = NO;
[self.activity startAnimating];
self.profilePic.image = [UIImage imageWithData:data];
NSLog(#"Profile pic shown");
}
else{
NSLog(#"Error 2: %#",error);
}
}];
}else{
self.profilePic.image = [UIImage imageNamed:#"profile#2.png"];
NSLog(#"Fail 1 : %#",error);
}
}];
}
Please help me.
It prints out profile pic shown. But it doesn't even use network to download an image.
I'm using Parse.com + Facebook user and I'm noticing something unusual that has not been happening previously. A user creates an account via Facebook, logs in, logs out, logs in, logs out, and then when they try logging in, that user gets deleted and another user gets created. Why could that be?
Here is my signup/signin code:
-(IBAction)facebookSignIn:(id)sender{
CLGeocoder *geo = [[CLGeocoder alloc] init];
if(![CLLocationManager locationServicesEnabled] || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied ){
UIAlertView *locationAlert = [[UIAlertView alloc]initWithTitle:#"Oops!" message:#"You must have location services enabled for this app to work properly" delegate:self cancelButtonTitle:nil otherButtonTitles:#"Okay", nil];
[locationAlert show];
}else{
[PFFacebookUtils logInWithPermissions:_permissions block:^(PFUser *aUser, NSError *suError) {
if(!aUser){
NSLog(#"not fbook user because %#",[suError description]);
if([[[suError userInfo] objectForKey:#"com.facebook.sdk:ErrorLoginFailedReason"] isEqualToString:#"com.facebook.sdk:SystemLoginDisallowedWithoutError"]){
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Error" message:#"Looks like you have Facebook authentication disabled! Go to Settings > Facebook > mySwapp and turn the switch ON"delegate:nil cancelButtonTitle:nil otherButtonTitles:#"Okay", nil];
[alert show];
}
else{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Error Signing In/Logging In" message:[suError localizedDescription] delegate:nil cancelButtonTitle:nil otherButtonTitles:#"Okay", nil];
[alert show];
}
}
else if(aUser.isNew){
NSLog(#"User is NEW");
[[FBRequest requestForMe] startWithCompletionHandler:
^(FBRequestConnection *connection,
NSDictionary<FBGraphUser> *user,
NSError *fbError) {
if (!fbError) {
NSLog(#"Facebook Request succeeded");
NSString *email = [user objectForKey:#"email"];
[aUser setEmail:email];
PFQuery *g = [PFQuery queryWithClassName:#"Counter"];
PFObject *cool = [g getObjectWithId:#"gpKDgNhwhw"];
[cool incrementKey:#"users"];
[cool saveEventually];
NSString *username = [NSString stringWithFormat:#"blahblah%d",[[cool objectForKey:#"users"] intValue]];
[aUser setUsername:username];
PFInstallation *installation = [PFInstallation currentInstallation];
[installation setObject:aUser forKey:#"user"];
[aUser setObject:#NO forKey:#"text"];
[aUser setObject:#YES forKey:#"snew"];
[aUser setObject:#"All" forKey:#"prefState"];
[aUser setObject:#"All" forKey:#"prefCat"];
[aUser setObject:#YES forKey:#"fnew"];
_type = #"facebook";
NSLog(#"Right before geopoint search....");
[PFGeoPoint geoPointForCurrentLocationInBackground:^(PFGeoPoint *geoPoint, NSError *error) {
if(!error){
NSLog(#"Got current geopoint!");
CLLocation *myLocation = [[CLLocation alloc]initWithLatitude:geoPoint.latitude longitude:geoPoint.longitude];
[geo reverseGeocodeLocation:myLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if(!error){
CLPlacemark *pl = placemarks[0];
NSString *zip = [pl.addressDictionary objectForKey:(NSString *)kABPersonAddressZIPKey];
NSString *city = [pl.addressDictionary objectForKey:(NSString *)kABPersonAddressCityKey];
NSString *state = [pl.addressDictionary objectForKey:(NSString *)kABPersonAddressStateKey];
if(city == nil ||state ==nil){
NSLog(#"city or state is nil");
if(city==nil){
NSLog(#"city is nil");
}
if(state==nil){
NSLog(#"state is nil");
}
}
[aUser setObject:city forKey:#"city"];
[aUser setObject:state forKey:#"state"];
[aUser setObject:zip forKey:#"zip"];
[aUser setObject:geoPoint forKey:#"geopoint"];
[aUser setObject:#NO forKey:#"pref"];
[aUser setObject:#20 forKey:#"radius"];
[aUser setObject:#0 forKey:#"postCount"];
[aUser saveInBackgroundWithBlock:^(BOOL succeeded, NSError *perror) {
if(!perror && succeeded){
[self performSegueWithIdentifier:#"registerMe" sender:self]; }
else{
CCAlertView *errorAlert = [[CCAlertView alloc]initWithTitle:#"Oops!" message:[NSString stringWithFormat:#"%#. If you have already registered, please login regularly and go to the settings tab and switch on \"Link to Facebook\".",[[perror userInfo] objectForKey:#"error"]]];
[errorAlert addButtonWithTitle:#"Okay" block:^{
[aUser deleteInBackground];
}];
[errorAlert show];
}
}];
}
else{
CCAlertView *errorAlert = [[CCAlertView alloc]initWithTitle:#"Error getting Facebook data" message:[[fbError userInfo] objectForKey:#"error"]];
[errorAlert addButtonWithTitle:#"Okay" block:^{
[aUser deleteInBackground];
}];
[errorAlert show];
}
}];
}
else{
CCAlertView *errorAlert = [[CCAlertView alloc]initWithTitle:#"Facebook Sign In/Sign Up" message:[[suError userInfo] objectForKey:#"error"]];
[errorAlert addButtonWithTitle:#"Okay" block:^{
[aUser deleteInBackground];
}];
[errorAlert show];
NSString *ciid = [[PFInstallation currentInstallation] objectId];
[PFCloud callFunctionInBackground:#"logError" withParameters:#{#"installation":ciid,#"message":[suError description],#"place":#"Facebook Sign In/Sign Up"} block:^(id object, NSError *error) {
if(error){
PFObject * errorObj = [PFObject objectWithClassName:#"Error"];
[errorObj setObject:ciid forKey:#"installation"];
[errorObj setObject:[suError description] forKey:#"message"];
[errorObj setObject:#"Facebook Sign In/Sign Up" forKey:#"place"];
[errorObj saveEventually];
}
}];
}
}];
}
}];
}
else{
NSLog(#"User is OLD");
[self performSegueWithIdentifier:#"showMain" sender:self]; }
}];
}
}
and here is my logout code:
- (IBAction)goBackNow:(id)sender {
NSLog(#"gobacknow called");
[PFUser logOut];
[self.navigationController popToRootViewControllerAnimated:YES];
}
You can try to add more stuff to logout method. e.g.
[FBSession.activeSession closeAndClearTokenInformation];
[FBSession.activeSession close];
[FBSession setActiveSession:nil];
PFInstallation *installation = [PFInstallation currentInstallation];
installation[#"user"] = [NSNull null];
[installation saveInBackground];
Also remember to [installation saveInBackground]; in your example
I am trying to update a PFObject called message. This PFObject has already been retrieved from the Parse Database and passed over from another view controller. I know that the PFObject is passed over correctly because I can NSLog it's value and it is correct.
With the following code, I add an object to one of the PFObject's keys:
[self.message addObject:#"blah" forKey:#"didRespond"];
I then try saving the updated PFObject to the Parse Database:
[self.message saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
NSLog(#"An error has occurred.");
}
}];
The above method always calls back with a succeeded value of 1, and there are never any errors. However, when I go and look at the PFObject in the Parse Data Browser, it's key does not contain the newly added object. It is still completely empty.
They key is an array, so I know I should be using addObject: and not setObject:
I have several other Parse saves happening in this same view controller, and throughout my app, and they all work perfectly fine, but for some reason this one will not. I have tried every type of save method Parse offers, including the synchronous save method, but nothing works.
What is even more strange, is this is a new version of my app and I am refactoring the code. My old version contains a giant mess of code, but what's amazing is the same PFObject is successfully updated in this old code! I even tried copying and pasting this code to my new version and it will not work, even though it will in the old version.
Here is the giant mess of code from my old version. If you search for the following code statement you will be able to locate it quickly:
[self.message addObject:currentUsersObjectId forKey:#"didRespond"];
Here is the full chunk of code, where the save is working and being reflected in the Data Browser. It consists of several nested asynchronous Parse saves:
-(void)uploadPhoto {
NSLog(#"self.image.size right before upload: %#", NSStringFromCGSize(self.image.size));
NSString *fileType;
NSString *halfOrFull;
if(self.image != nil) {
fileType = #"image";
halfOrFull = #"full";
NSData *imageData = UIImageJPEGRepresentation(self.image, 0.7);
PFFile *imageFile = [PFFile fileWithName:#"Image.jpg" data:imageData];
NSString *originalSender = [[NSString alloc]init];
originalSender = [self.message objectForKey:#"senderId"];
NSLog(#"PFFile has been created: %#", imageFile);
[imageFile saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if(error) {
NSLog(#"There has been an error: %# %#", error, [error userInfo]);
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:#"An error occurred!" message:#"Please try sending your message again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
} else {
[self.afterPhotoView setHidden:YES];
PFObject *returnMessage = [PFObject objectWithClassName:#"Messages"];
[returnMessage setObject:imageFile forKey:#"file"];
[returnMessage setObject:fileType forKey:#"fileType"];
[returnMessage addObject:originalSender forKey:#"recipientIds"];
[returnMessage setObject:[[PFUser currentUser]objectId] forKey:#"senderId"];
[returnMessage setObject:[[PFUser currentUser]username]forKey:#"senderName"];
[returnMessage setObject:halfOrFull forKey:#"halfOrFull"];
NSString *originalSender = [[NSString alloc]init];
originalSender = [self.message objectForKey:#"senderName"];
[returnMessage setObject:originalSender forKey:#"originalSender"];
[returnMessage saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if(error) {
NSLog(#"There was an error: %# %#", error, [error userInfo]);
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:#"An error occurred!" message:#"Please try sending your message again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
} else {
//Everything was successful.
NSLog(#"Everything was successful.");
if(succeeded == 1) {
NSLog(#"Succeeded value right before 2nd save: %d", succeeded);
NSString *currentUsersObjectId = [[NSString alloc]init];
PFUser *user = [PFUser currentUser];
currentUsersObjectId = user.objectId;
[self.message addObject:currentUsersObjectId forKey:#"didRespond"];
[self.message saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if(error) {
NSLog(#"There was an error: %# %#", error, [error userInfo]);
self.uploadPhotoAlertView = [[UIAlertView alloc]initWithTitle:#"An error occurred!" message:#"Please try sending your message again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[self.uploadPhotoAlertView show];
} else {
//Everything was successful.
NSLog(#"Everything was successful.");
if(succeeded == 1) {
//[self performSegueWithIdentifier:#"segueToInbox" sender:self];
NSString *originalSender2 = [[NSString alloc]init];
originalSender2 = [self.message objectForKey:#"senderName"];
self.photoUploadAlertViewMessage = [[NSString alloc]initWithFormat:#"You just finished going halfsies with %#!", originalSender2];
//PFFile *imageFile = [self.message objectForKey:#"file"];
self.finishedImageFile = imageFile;
self.finishedImageFileURL = [[NSURL alloc]initWithString:self.finishedImageFile.url];
self.uploadPhotoAlertView = [[UIAlertView alloc]initWithTitle:nil message:self.photoUploadAlertViewMessage delegate:self cancelButtonTitle:#"Sweet!" otherButtonTitles:nil];
[self.uploadPhotoAlertView show];
//[self.sharePhotoView setHidden:NO];
}
//[self performSegueWithIdentifier:#"segueToInbox" sender:self];
}
}];
}
}
}];
}
}];
}
}
In the Parse docs, it says that you can check if a user is linked to a Facebook account, but is there any way to do it vice versa? For example, suppose the user clicks a button to sign in with Facebook, since [PFUser currentUser] is nil (because the user hasn't logged in yet), Parse will create a NEW account for that user since you can't use [PFFacebookUtils isLinkedWithUser: [PFUser currentUser]]. It seems like the only way to link an account is after the user has logged in regularly(i.e. entering their username and password), but that's really inconvenient. What if the user has already created an accounted manually (by filling out a the registration form I provide) and then decides to link their Facebook account? SO is there anyway to check if a Facebook account is linked with a user in general rather than checking it against a specific user?
Ok here is the solution. Basically iterate through every user and see if Facebook account is linked with that. based on that, link or create a new account. Here is code:
PFQuery *userQuery = [PFUser query];
[userQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
NSUInteger count = [objects count];
BOOL linked = NO;
for(NSUInteger i = 0; i < count; i++){
PFUser *checkUser = objects[i];
if([PFFacebookUtils isLinkedWithUser:checkUser]){
linked = YES;
NSLog(#"profile is linked to a user");
break;
}
}
if(linked == YES){
[PFFacebookUtils logInWithPermissions:_permissions block:^(PFUser *user, NSError *error) {
if(!user){
NSLog(#"facebook cancelled");
}
else{
_type = #"twitter";
[self performSegueWithIdentifier:#"showMain" sender:self]; }
}
];
}
else{
CCAlertView *ask = [[CCAlertView alloc]initWithTitle:#"Are you already registered" message:nil];
[ask addButtonWithTitle:#"No" block:^{
[PFFacebookUtils logInWithPermissions:_permissions block:^(PFUser *user, NSError *error) {
if(!user){
NSLog(#"Facebook cancelled");
}
else if(user.isNew){
_type = #"facebook";
[self performSegueWithIdentifier:#"showMain" sender:self]; }
else{
[self performSegueWithIdentifier:#"showMain" sender:self]; }
}];
}];
[ask addButtonWithTitle:#"Yes" block:^{
CCAlertView *log = [[CCAlertView alloc]initWithTitle:#"Enter username and password" message:nil];
[log setAlertViewStyle:UIAlertViewStyleLoginAndPasswordInput];
UITextField *un = [log textFieldAtIndex:0];
UITextField *pw = [log textFieldAtIndex:1];
[log addButtonWithTitle:#"Cancel" block:nil];
[log addButtonWithTitle:#"Enter" block:^{
[PFUser logInWithUsernameInBackground:[un text] password:[pw text] block:^(PFUser *user, NSError *error) {
if(user){
[PFFacebookUtils linkUser:user permissions:_permissions block:^(BOOL succeeded, NSError *error) {
if(succeeded){
NSLog(#"linked");
[self performSegueWithIdentifier:#"showMain" sender:self]; }
else{
NSLog(#"couldnt link");
}
}];
}
else{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Oops!" message:[error userInfo] delegate:self cancelButtonTitle:nil otherButtonTitles:#"okay", nil];
[alert show];
}
}];
}];
[log show];
}];
[ask show];
}
}];
- (IBAction)LoginViaFb:(id)sender {
// Set permissions required from the facebook user account
NSArray *permissionsArray = #[ #"user_email", #"user_relationships", #"user_birthday", #"user_location"];
// Login PFUser using facebook
[PFFacebookUtils logInWithPermissions:permissionsArray block:^(PFUser *user, NSError *error) {
NSLog(#"user=%#",user);
if (!user) {
if (!error) {
NSLog(#"Uh oh. The user cancelled the Facebook login.");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Log In Error" message:#"Uh oh. The user cancelled the Facebook login." delegate:nil cancelButtonTitle:nil otherButtonTitles:#"Dismiss", nil];
[alert show];
} else {
NSLog(#"Uh oh. An error occurred --- %#", error);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Log In Error" message:[error description] delegate:nil cancelButtonTitle:nil otherButtonTitles:#"Dismiss", nil];
[alert show];
}
} else if (user.isNew) {
NSLog(#"User with facebook signed up and logged in!");
} else {
NSLog(#"User with facebook logged in!");
}
// If the user is already logged in, display any previously cached values before we get the latest from Facebook.
if ([PFUser currentUser]) {
[self updateProfile];
}
// Send request to Facebook
FBRequest *request = [FBRequest requestForMe];
[request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
// handle response
if (!error) {
// Parse the data received
NSDictionary *userData = (NSDictionary *)result;
NSLog(#"userData -------- %#",userData);
NSString *facebookID = userData[#"id"];
NSMutableDictionary *userProfile = [NSMutableDictionary dictionaryWithCapacity:7];
if (facebookID) {
userProfile[#"facebookId"] = facebookID;
}
if (userData[#"name"]) {
userProfile[#"name"] = userData[#"name"];
}
if (userData[#"location"][#"name"]) {
userProfile[#"location"] = userData[#"location"][#"name"];
}
if (userData[#"gender"]) {
userProfile[#"gender"] = userData[#"gender"];
}
if (userData[#"birthday"]) {
userProfile[#"birthday"] = userData[#"birthday"];
}
if (userData[#"relationship_status"]) {
userProfile[#"relationship"] = userData[#"relationship_status"];
}
[[PFUser currentUser] setObject:userProfile forKey:#"profile"];
[[PFUser currentUser] saveInBackground];
[self updateProfile];
} else if ([[[[error userInfo] objectForKey:#"error"] objectForKey:#"type"]
isEqualToString: #"OAuthException"]) { // Since the request failed, we can check if it was due to an invalid session
NSLog(#"The facebook session was invalidated");
} else {
NSLog(#"Some other error: %#", error);
}
}];
}];
After writing this code, my log shows:
user=(null)
Uh oh. An error occurred ---
Error Domain=com.facebook.sdk Code=2 "The operation couldn’t be completed. (com.facebook.sdk error 2.)" UserInfo=0xbf6f0c0 {com.facebook.sdk:ErrorLoginFailedReason=com.facebook.sdk:SystemLoginDisallowedWithoutError, com.facebook.sdk:ErrorSessionKey=, expirationDate: (null), refreshDate: (null), attemptedRefreshDate: 0001-12-30 00:00:00 +0000, permissions:(null)>}
Please help, where i am doing mistake? and Thanks in advance.