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
Related
I am trying to login a user through facebook in my parse.com app. I have all the ids and appdelegate methods in place.
I have created a view in the storyboard and made that a facebook login button and then i have connected it to my .h file as a IBAction.
my code:
- (IBAction)fblogin:(FBSDKLoginButton *)sender {
[PFFacebookUtils logInInBackgroundWithReadPermissions:#[#"public_profile", #"email"] block:^(PFUser *user, NSError *error) {
if (error) {
// NSLog(#"Uh oh. The user cancelled the Facebook login.");
UIAlertView *alertVeiw = [[UIAlertView alloc] initWithTitle:#"Sorry" message:[error.userInfo objectForKey:#"error"] delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alertVeiw show];
} else if (!user) {
UIAlertView *alertVeiw = [[UIAlertView alloc] initWithTitle:#"Sorry" message:#"You cancelled Login, try again!" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alertVeiw show];
}else {
// NSLog(#"User logged in through Facebook!");
// [self dismissViewControllerAnimated:YES completion:NULL];
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:#{#"fields": #"first_name, last_name, email, public_profile"}];
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error)
{
if (error)
{
UIAlertView *alertVeiw = [[UIAlertView alloc] initWithTitle:#"Sorry" message:[error.userInfo objectForKey:#"error"] delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alertVeiw show];
} else if ([[error userInfo][#"error"][#"type"] isEqualToString: #"OAuthException"]) { // Since the request failed, we can check if it was due to an invalid session
// NSLog(#"The facebook session was invalidated");
[PFFacebookUtils unlinkUserInBackground:[PFUser currentUser]];
}
else {
NSDictionary *userData = (NSDictionary *)result;
// [self requestFacebookUser:user];
NSString *name = userData[#"name"];
NSString *email = userData[#"email"];
user.username = name;
user.email = email;
[user saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error)
{
if (error)
{
UIAlertView *alertVeiw = [[UIAlertView alloc] initWithTitle:#"Sorry" message:[error.userInfo objectForKey:#"error"] delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alertVeiw show];
}
else {
// [self dismissViewControllerAnimated:NO completion:nil];
//[self.navigationController popToRootViewControllerAnimated:NO];
[self performSegueWithIdentifier:#"inbox" sender:self];
}
}];
}
}];
}
}];
}
The faccebook web page opens when i press login facebook button then we sign in and then nothing happens.
Please help me implement facebook login step by step correctly.
EDIT:
app delegate:
[PFFacebookUtils initializeFacebookWithApplicationLaunchOptions:launchOptions];
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [[FBSDKApplicationDelegate sharedInstance] application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation];
}
applicationWillEnterForeGround:
[FBSDKAppEvents activateApp];
then:
along with your(SanitLee) answer i have these methods:
- (void)loginViewFetchedUserInfo:(FBSDKLoginManager *)loginView
user:(FBSDKProfile*)user {
}
-(void)loginButton:(FBSDKLoginButton *)loginButton didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result error:(NSError *)error{
// [self performSegueWithIdentifier:#"inbox" sender:self];
}
-(void)loginButtonDidLogOut:(FBSDKLoginButton *)loginButton{
}
-(void)loginButtonClicked{
}
i also get this error on whose view is not in the window hierarchy!
Here's how I did it and it works for me.
Firstly, import this in your m file:
#import <ParseFacebookUtils/PFFacebookUtils.h>//fb login for parse
Then the following codes should do what you want:
- (IBAction)loginButtonTouchHandler:(id)sender {
NSArray *permissionsArray = #[ #"user_about_me", #"user_relationships", #"user_birthday", #"user_location"];
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
[PFFacebookUtils logInWithPermissions:permissionsArray block:^(PFUser *user, NSError *error) {
if (!user) {
NSString *errorMessage = nil;
if (!error) {
NSLog(#"Uh oh. The user cancelled the Facebook login.");
errorMessage = NSLocalizedString(#"Uh oh. The user cancelled the Facebook login.", nil);
} else {
NSLog(#"Uh oh. An error occurred: %#", error);
errorMessage = [error localizedDescription];
}
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Log In Error", nil) message:errorMessage delegate:nil cancelButtonTitle:nil otherButtonTitles:NSLocalizedString(#"Dismiss", nil), nil];
[MBProgressHUD hideHUDForView:self.view animated:YES];
[alert show];
} else {
if (user.isNew) {
NSLog(#"User with facebook signed up and logged in!");
[self _loadData];
} else {
NSLog(#"User with facebook logged in!");
}
[MBProgressHUD hideHUDForView:self.view animated:YES];
[self _presentNextViewControllerAnimated:YES];
}
}];
}
- (void)_presentNextViewControllerAnimated:(BOOL)animated {
PAWWallViewController *wallViewController = [[PAWWallViewController alloc] initWithNibName:nil bundle:nil];
[(UINavigationController *)self.presentingViewController pushViewController:wallViewController animated:NO];
[self.presentingViewController dismissModalViewControllerAnimated:YES];
}
- (void)_loadData {
FBRequest *request = [FBRequest requestForMe];
[request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if (!error) {
PFUser *user = [PFUser currentUser];
NSDictionary *userData = (NSDictionary *)result;
NSString *facebookID = userData[#"id"];
NSString *name = userData[#"name"];
NSString *email = userData[#"email"];
NSString *location = userData[#"location"][#"name"];
NSString *gender = userData[#"gender"];
NSString *birthday = userData[#"birthday"];
NSString *relationship = userData[#"relationship_status"];
NSString *facebookLink = [NSString stringWithFormat:#"Facebook.com/%#", facebookID];
NSURL *pictureURL = [NSURL URLWithString:[NSString stringWithFormat:#"https://graph.facebook.com/%#/picture?type=large&return_ssl_resources=1", facebookID]];
NSLog(#"facebookID --> %#", facebookID);
NSLog(#"name --> %#", name);
NSLog(#"email --> %#", email);
//for profile image
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:pictureURL];
// Run network request asynchronously
[NSURLConnection sendAsynchronousRequest:urlRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (connectionError == nil && data != nil) {
PFFile *userImageFile = [PFFile fileWithName:#"userImage.jpg" data:data];
if (userImageFile) [user setObject:userImageFile forKey:kPAWParseUserImageKey];
}
[user setObject:facebookID forKey:kPAWParseUsernameKey]; //initially use fb id as username to avoid duplication
[user setObject:name forKey:kPAWParseRealnameKey];
[user setObject:facebookLink forKey:kPAWParseFacebookKey];
[user saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
if (succeeded) {
NSLog(#"fb user saved successfully");
}
} else {
NSLog(#"fb user saved unsuccessfully");
}
}];
}];
} else if ([[[[error userInfo] objectForKey:#"error"] objectForKey:#"type"]
isEqualToString: #"OAuthException"]) {
NSLog(#"The facebook session was invalidated");
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Log out of Spotpost?", nil) message:nil delegate:self cancelButtonTitle:NSLocalizedString(#"Log out", nil) otherButtonTitles:NSLocalizedString(#"Cancel", nil), nil];
[alertView show];
} else {
NSLog(#"Some other error: %#", error);
}
}];
}
And here is how I did config in app delegate:
#import <ParseFacebookUtils/PFFacebookUtils.h> //fb login for parse
....
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
[PFFacebookUtils initializeFacebook]; //fb login for parse
return YES;
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
....
[FBAppCall handleDidBecomeActiveWithSession:[PFFacebookUtils session]]; //fb login for parse
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
return [FBAppCall handleOpenURL:url
sourceApplication:sourceApplication
withSession:[PFFacebookUtils session]];
}
- (void)applicationWillTerminate:(UIApplication *)application {
[[PFFacebookUtils session] close];
}
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.
I am new in iOS Development, I am trying to do get Details of User from Facebook. Here is my code which i am used but when it called my app is hang. In below code it can not worked when i can not Login with device in Facebook in Setting>Facebook. Please help me for this.
-(Void)LoginWithFB {
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *facebookAccountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
SLComposeViewController *vc = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
id options = #{
ACFacebookAppIdKey: #"1501842240102594",
ACFacebookPermissionsKey: #[ #"email"],
};
[accountStore requestAccessToAccountsWithType:facebookAccountType
options:options
completion:^(BOOL granted, NSError *error) {
if (granted)
{
// Return back logined facebook Account
ACAccount *fbAccount = [[accountStore accountsWithAccountType:facebookAccountType] lastObject];
// Do What you want...
// Request friend list
//http://graph.facebook.com/000000000/picture
SLRequest *friendsListRequest = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodGET
URL: [[NSURL alloc] initWithString:#"https://graph.facebook.com/me"]parameters:nil];
friendsListRequest.account = fbAccount;
[friendsListRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
// Parse response JSON
NSError *jsonError = nil;
NSDictionary *dictionaryForFacebookData = [NSJSONSerialization JSONObjectWithData:responseData
options:NSJSONReadingAllowFragments
error:&jsonError];
// NSString *proficePicture = [NSString stringWithFormat:#"http://graph.facebook.com/415790901901979/picture"];
NSMutableDictionary *dictionaryParameter = [[NSMutableDictionary alloc]init];
[dictionaryParameter setObject:#"facebook" forKey:#"registrationsource"];
[dictionaryParameter setObject:[dictionaryForFacebookData objectForKey:#"first_name"] forKey:#"firstname"];
[dictionaryParameter setObject:[dictionaryForFacebookData objectForKey:#"last_name"] forKey:#"lastname"];
[dictionaryParameter setObject:[dictionaryForFacebookData objectForKey:#"email"] forKey:#"email"];
[dictionaryParameter setObject:#"yes" forKey:#"status"];
WebServiceClass *objectToCallApi = [[WebServiceClass alloc]init];
NSDictionary *dictionaryReturnValue = [objectToCallApi callAPIWebservice:dictionaryParameter stringURL:[[Singelton sharedInstance] passMethodName:#"login"]];
if (![[dictionaryReturnValue objectForKey:#"success"] isEqualToString:#"1"])
{
[UIAlertView showWithTitle:ALERT_TITLE message:[dictionaryReturnValue objectForKey:#"message"] handler:^(UIAlertView *alertview, NSInteger buttonindex){
}];
}
if ([[dictionaryReturnValue objectForKey:#"success"] isEqualToString:#"1"])
{
APP_DELEGATE.intTabbarNumber = 0;
NSMutableDictionary *data =[[NSMutableDictionary alloc]init];
[data setObject:[NSString stringWithFormat:#"%# %#",[dictionaryReturnValue objectForKey:#"firstname"], [dictionaryReturnValue objectForKey:#"lastname"]] forKey:#"fullname"];
[data setObject:dictionaryReturnValue[#"username"] forKey:#"username"];
[data setObject:dictionaryReturnValue[#"email"] forKey:#"email"];
[data setObject:dictionaryReturnValue[#"userid"] forKey:#"userid"];
NSMutableArray *arrayOfExistingUser;
if([[NSUserDefaults standardUserDefaults] valueForKey:#"Users"] != nil)
{
arrayOfExistingUser = [[[NSUserDefaults standardUserDefaults] valueForKey:#"Users"] mutableCopy];
for (int i=0; i<arrayOfExistingUser.count; i++)
{
if ([[[arrayOfExistingUser objectAtIndex:i]objectForKey:#"userid"] isEqualToString:[data objectForKey:#"userid"]])
{
[arrayOfExistingUser removeObjectAtIndex:i];
}
}
}
else
{
arrayOfExistingUser = [[NSMutableArray alloc]init];
}
[arrayOfExistingUser addObject:data];
[[NSUserDefaults standardUserDefaults] setObject:arrayOfExistingUser forKey:#"Users"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSUserDefaults standardUserDefaults]setObject:dictionaryReturnValue forKey:#"dictionaryForLoginData"];
if ([[dictionaryReturnValue objectForKey:#"role"] isEqualToString:#"teacher"])
{
[APP_DELEGATE createTabbarInstanceForTeacher];
}
else if ([[dictionaryReturnValue objectForKey:#"role"] isEqualToString:#"student"])
{
[APP_DELEGATE createTabbarInstanceForstudent];
}
else if ([[dictionaryReturnValue objectForKey:#"role"] isEqualToString:#"parent"])
{
[APP_DELEGATE createTabbarInstanceForParent];
}
}
}];
}
else
{
SLComposeViewController *controller = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[controller.view resignFirstResponder];
controller.view.hidden = YES;
[self presentViewController:controller animated:NO completion:nil];
}
}];
}
in .h file
#import <Accounts/Accounts.h>
#import <Social/Social.h>
#property (nonatomic, strong) ACAccountStore *accountStore;
#property (nonatomic, strong) ACAccount *facebookAccount;
in .m file
- (void) getuserdetails
{
self.accountStore = [[ACAccountStore alloc]init];
ACAccountType *FBaccountType= nil;
//[self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
if (! FBaccountType) {
FBaccountType = [_accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
}
NSString *key =kFBAppId;
NSDictionary *dictFB = [NSDictionary dictionaryWithObjectsAndKeys:key,ACFacebookAppIdKey,#[#"email"],ACFacebookPermissionsKey, nil];
[self.accountStore requestAccessToAccountsWithType:FBaccountType options:dictFB completion:
^(BOOL granted, NSError *e)
{
if (granted)
{
NSArray *accounts = [self.accountStore accountsWithAccountType:FBaccountType];
self.facebookAccount = [accounts lastObject];
NSLog(#"facebook account =%#",self.facebookAccount);
[self get];
}
else
{
NSLog(#"fb error %#",e.description);
dispatch_async(dispatch_get_main_queue(), ^
{
[self performSelectorOnMainThread:#selector(hideLoader) withObject:nil waitUntilDone:YES];
NSLog(#"%#",e.description);
if([e code]== ACErrorAccountNotFound)
{
UIAlertView* alt = [[UIAlertView alloc] initWithTitle:#"Account not found"
message:msgSetUpFBAccount delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok",nil];
[alt show];
}
else
{
UIAlertView* alt = [[UIAlertView alloc] initWithTitle:msgFBAccessDenied
message:#"" delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok",nil];
[alt show];
}
});
NSLog(#"error getting permission %#",e);
}
}];
}
-(void)get
{
NSURL *requestURL = [NSURL URLWithString:#"https://graph.facebook.com/me"];
SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodGET
URL:requestURL
parameters:nil];
request.account = self.facebookAccount;
[request performRequestWithHandler:^(NSData *data,
NSHTTPURLResponse *response,
NSError *error)
{
if(!error)
{
list =[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSLog(#"Dictionary contains: %#", list );
if([list objectForKey:#"error"]!=nil)
{
[self attemptRenewCredentials];
}
dispatch_async(dispatch_get_main_queue(),^{
});
}
else
{
[self performSelectorOnMainThread:#selector(hideLoader) withObject:nil waitUntilDone:YES];
NSLog(#"error from get%#",error);
}
}];
}
-(void)attemptRenewCredentials{
[self.accountStore renewCredentialsForAccount:(ACAccount *)self.facebookAccount completion:^(ACAccountCredentialRenewResult renewResult, NSError *error){
if(!error)
{
switch (renewResult) {
case ACAccountCredentialRenewResultRenewed:
NSLog(#"Good to go");
[self get];
break;
case ACAccountCredentialRenewResultRejected:
{
NSLog(#"User declined permission");
UIAlertView* alt = [[UIAlertView alloc] initWithTitle:#"Access Denied"
message:#"You declined permission" delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok",nil];
[alt show];
break;
}
case ACAccountCredentialRenewResultFailed:
{
NSLog(#"non-user-initiated cancel, you may attempt to retry");
UIAlertView* alt = [[UIAlertView alloc] initWithTitle:#"Access Denied"
message:#"non-user-initiated cancel, you may attempt to retry" delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok",nil];
[alt show];
break;
}
default:
break;
}
}
else{
//handle error gracefully
NSLog(#"error from renew credentials%#",error);
}
}];
}
In your method signature - (Void)LoginWithFB; Void is not a type but void is. So that might be the problem.
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.