FBSDKLoginManager logInWithPublishPermissions always returns isCancelled=YES

百般思念 提交于 2019-11-27 08:36:10

You should try adding in your AppDelegate didFinishLaunchingWithOptions :

return [[FBSDKApplicationDelegate sharedInstance] application:application
                                    didFinishLaunchingWithOptions:launchOptions];

This would get u [FBSDKAccessToken currentAccessToken] when user is logged in.

and

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
    return [[FBSDKApplicationDelegate sharedInstance] application:application
                                                          openURL:url
                                                sourceApplication:sourceApplication
                                                       annotation:annotation];
}

If this method is not present into AppDelegate then it results into cancelled state.

Refer to : https://developers.facebook.com/docs/ios/getting-started#startcoding

This can happen when your Facebook App doesn't have "publish_actions" permission, or you're not using a test user.

On Facebook, go to manage your app, then make sure that the Facebook user you're using is defined under "Roles" as an admin or tester.

If it's not a test user or admin - Facebook will require "publish_actions" permission to be reviewed and approved before allowing your app to use it, until then you'll receive a "isCancelled=YES" result.

After testing your app with this permission, it is possible to submit this permission for review, you'll need to upload a binary that demonstrates usage of this permission with exact details on how to use it. After it's approved, you'll be able to use it with non-test Facebook users.

Since FBSDKLoginKit 4.6.0, the logInWithReadPermissions and logInWithPublishPermissions methods of FBSDKLoginManager seems to have additional fromViewController argument and use that to present modals.

I was calling logInWithPublishPermissions inside the callback of logInWithReadPermissions, which at that point the modal is not fully dismissed yet. (I know it's a bad practice to ask permission when it's not needed, but in my case this seems to be the right place to do.) This cause it to fail with isCancelled equals to YES. I added some delay and wait for the modal to be fully dismissed fixed the problem.

I had the same problem when I landed here, turns out I was only using the deprecated application openURL method because i was using google sign in too. To support iOS 8 and before you have to implement both the current and the deprecated method:

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    return GIDSignIn.sharedInstance().handle(url, sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String!, annotation: options[UIApplicationOpenURLOptionsKey.annotation]) || FBSDKApplicationDelegate.sharedInstance().application(app, open: url, sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String, annotation: options[UIApplicationOpenURLOptionsKey.annotation])
}

func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
    return GIDSignIn.sharedInstance().handle(url, sourceApplication: sourceApplication, annotation: annotation) || FBSDKApplicationDelegate.sharedInstance().application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
}

The deprecated is the second.

Note: The FBSDK method is added after the google one with an or "||" operator but the order doesn't matter and if you wanna only use facebook method just erase the method and the or operator.

Note 2: As swift 3 still stabilizing the method name can change I suggest you always use the auto complete from XCode when overriding and implementing a delegate's method.

Hope this Helps o/

This method works in iOS 9

// Facebook Login Completion delegate
- (void)loginButton:(FBSDKLoginButton *)loginButton didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result error:(NSError *)error
{
    if (result){
        NSLog(@"%@",result);
        NSLog(@"%@",result.grantedPermissions);
       [self getFacebookData:result];
     }
}  

- (void)getFacebookData:(FBSDKLoginManagerLoginResult *)result{

   if (![result.grantedPermissions containsObject:@"email"])
   {
      FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
      login.loginBehavior = FBSDKLoginBehaviorWeb;
      [login logInWithReadPermissions:@[@"email"] fromViewController:self handler:^(FBSDKLoginManagerLoginResult *result, NSError *error)
       {
         if (error)
         {
             // Process error
         }
         else if (result.isCancelled)
         {
             // Handle cancellations
         }
         else
         {
             if ([result.grantedPermissions containsObject:@"email"])
             {
                 NSLog(@"result is:%@",result);
                 if ([FBSDKAccessToken currentAccessToken]) {
                     [[[FBSDKGraphRequest alloc] initWithGraphPath:@"me" parameters:@{@"fields": @"first_name, last_name, email, id"}]
                      startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
                          if (!error) {
                              NSLog(@"fetched user:%@", result);
                              [self registerWithFacebook:result];
                          }else{
                              NSLog(@"%@",error);
                          }
                      }];
                 }


             }
         }
     }];


 }else{
    if ([FBSDKAccessToken currentAccessToken]) {
        [[[FBSDKGraphRequest alloc] initWithGraphPath:@"me" parameters:@{@"fields": @"first_name, last_name, email, id"}]
         startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
             if (!error) {
                 NSLog(@"fetched user:%@", result);
                 [self registerWithFacebook:result];
             }else{
                 NSLog(@"%@",error);
             }
         }];
    }
}

}

NOTE : Use FBSDKLoginBehaviorWeb instead of FBSDKLoginBehaviorBrowser. This will surely work

gravy

Also, make sure you are not calling for FBSDKAccessToken.currentAccessToken INSIDE your didFinishLaunchingWithOptions method. The setup in didFinishLaunchingWithOptions needs to complete so the token can initialize before you try to log in to Facebook.

Salman Ghumsani

FBSDKLoginManagerLoginResult.isCancelled is unexpectedly YES:

The SDK will report a cancellation if the user explicitly taps a cancel button in the login dialogs, or if they manually app switch back to your app (known as an implicit cancellation). You should make sure you are not initiating a login flow as part of your app delegate's lifecycle (such as starting a login inside application:openURL:sourceApplication:annotation:) as that will mimic an implicit cancellation. If you must, dispatch the login initiation later to the main queue so that the app delegate's lifecycle completes first.

I also faced the same issue and i spent almost 2 hours to resolve the issue. What i did is

FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
**[login logOut];** // adding this single line fixed my issue
[login logInWithReadPermissions: @[@"public_profile"] fromViewController:self  handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
     if (error) {
         NSLog(@"Process error");
     } else if (result.isCancelled) {
         NSLog(@"Cancelled");
     } else {
         NSLog(@"Logged in");
         [self GetData];
     }
 }] // I called this logout function 

and the issue was fixed

i was using both google and Facebook login so i had to implement my openURL method like this, iOS 9+

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
    if ([[url absoluteString] containsString:@"YOURFBID"]) {
        return [[FBSDKApplicationDelegate sharedInstance] application:app openURL:url options:options];
    } else {
        return [[GIDSignIn sharedInstance] handleURL:url
                                   sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]
                                          annotation:options[UIApplicationOpenURLOptionsAnnotationKey]];
    }
    return NO;
}

// you can perform further any operations using the access token

- (void)GetData {
    if ([FBSDKAccessToken currentAccessToken]) {
        NSDictionary *AccessToken = [FBSDKAccessToken currentAccessToken];
        [[[FBSDKGraphRequest alloc] initWithGraphPath:@"me" parameters:@{@"fields": @"id, name, first_name, picture.type(large) ,last_name"}]
         startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
             if (!error) {
                 //NSLog(@"fetched user:%@", result);
                 //NSDictionary *Result = result;
                 NSDictionary *params = [NSMutableDictionary dictionaryWithObject:[AccessToken tokenString] forKey:@"access_token"];

             } else {
                 [self showAlertController:@"Error" message:error.localizedDescription];
             }
         }];
    } }
Cong Wang
(BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
            options:(nonnull NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
    return [[FBSDKApplicationDelegate sharedInstance] application:application
                                                          openURL:url
                                                          options:options];
}

// **Still need this for iOS8**
- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(nullable NSString *)sourceApplication
         annotation:(nonnull id)annotation
{
    return [[FBSDKApplicationDelegate sharedInstance] application:application
                                                          openURL:url
                                                sourceApplication:sourceApplication
                                                       annotation:annotation];
}

1.check already added

[[FBSDKApplicationDelegate sharedInstance] application:application
                             didFinishLaunchingWithOptions:launchOptions];

2.check already added

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(nullable NSString *)sourceApplication
         annotation:(nonnull id)annotation
{
    return [[FBSDKApplicationDelegate sharedInstance] application:application
                                                          openURL:url
                                                sourceApplication:sourceApplication
                                                       annotation:annotation];
}

3. write this statement [FBSDKProfile enableUpdatesOnAccessTokenChange:YES]; before

[[FBSDKApplicationDelegate sharedInstance] application:application
                         didFinishLaunchingWithOptions:launchOptions];

4.call logInWithReadPermissions method in dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{}

Hohua Huang

call this methord,

FBSDKLoginManager *loginManager = [[FBSDKLoginManager alloc] init];
[loginManager logInWithReadPermissions:@[@"user_friends"] handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
   code
}];
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!