My application is iOS7 only, and in the interest of preserving the headaches, I decided not to use the SDK for authentication and instead rely on iOS ACAccountStore. Unfortunately, I still have headaches.
I have a class called FacebookService with one method login. I will post the code below, but overall I do the standard dance of setting up the instance ACAccountStoreand then invoking requestAccessToAccountsWithType. In the completion block, if it grantedreturns false, I inform the user and a short circuit.
If grantedtrue, then my code used to make the assumption that I had everything I needed to get the oauthToken user using the following code:
ACAccount *fbAccount = [[accountStore accountsWithAccountType:fbAccountType] lastObject];
ACAccountCredential *fbCredential = [fbAccount credential];
NSString *accessToken = [fbCredential oauthToken];
I get oauthTokenfrom ACAccount#credential, and the first thing that is weird is that according to the documentation :
For privacy reasons, this property (not available after saving the account.
I can definitely tell you that in most cases this property is absolutely accessible, and I can use it to send to my server to find a user who has previously passed the verification.
However, several times, the value will actually be zero. And in each case, when this happens, it can be solved if the user goes to "Settings"> "Facebook"> "Disable application"> "Enable our application." They will return to our application, click "Sign in to Facebook", and everything works fine.
So here are my questions:
- oauthToken FB ACAccount? , , , , .
- , , "", , ? ?
- , , , oauthToken?
- - , , ?
:
- (void)login
{
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *fbAccountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSString *appId = [[Environment sharedInstance] fbAppId];
NSDictionary *fbOptions = @{
ACFacebookAppIdKey : appId,
ACFacebookPermissionsKey : [@"email,user_birthday,user_hometown,user_location,user_photos" componentsSeparatedByString:@","],
ACFacebookAudienceKey: ACFacebookAudienceEveryone
};
[accountStore requestAccessToAccountsWithType:fbAccountType options:fbOptions completion:^(BOOL granted, NSError *error) {
NSString *message;
NSString *title;
if (!granted) {
if (!error || error.code == ACErrorPermissionDenied) {
title = @"AFAR Needs Your Permission";
message = @"Your Facebook account is configured in Settings. Go to Settings and enable AFAR.";
} else if (error.code == ACErrorAccountNotFound) {
title = @"No Facebook Account";
message = @"There are no Facebook accounts configured. You can add or create a Facebook account in Settings.";
}
if (message) {
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AfarFacebookLoginDidNotSucceed object:nil];
[UIAlertView simpleAlertWithTitle:title message:message];
});
}
return;
}
ACAccount *fbAccount = [[accountStore accountsWithAccountType:fbAccountType] lastObject];
ACAccountCredential *fbCredential = [fbAccount credential];
NSString *accessToken = [fbCredential oauthToken];
if ([accessToken isEmpty]) {
message = @"You need to allow AFAR access to your Facebook account. Please visit Settings > Facebook and look for the AFAR entry. Turn the AFAR setting off, then back on.";
title = @"Problem Connecting to Facebook";
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AfarFacebookLoginDidNotSucceed object:nil];
[UIAlertView simpleAlertWithTitle:title message:message];
});
return;
}
[SessionAPIService signInUsingFacebookToken:accessToken withBlock:^(NSError *error) {
if (!error) {
[[NSNotificationCenter defaultCenter] postNotificationName:AFARCurrentUserDidSignInNotificatioName object:nil];
}
}];
}];
}