FBSDKLoginManager logInWithPublishPermissions всегда возвращает isCancelled=да

у меня возникли проблемы с выяснением, как войти пользователя в мое приложение. [FBSDKAccessToken currentAccessToken] равно нулю, поэтому я звоню:

[[[FBSDKLoginManager alloc] init] logInWithPublishPermissions:@[@"publish_actions"] handler:…];

согласно прилагаемого образца проекта. Это переключается на приложение Facebook, но в сообщении говорится: "Вы уже авторизованы Название.". Я нажимаю OK, и он возвращается в приложение, но grantedPermissions и declinedPermissions как nil на следствии, и isCancelled is YES. [FBSDKAccessToken currentAccessToken] по-прежнему nil.

Я не могу понять, как я должен был получить currentAccessToken для заполнения. Мне кажется, это призыв к logInWithPublishPermissions должен делать это, но это не так.

11 ответов


вы должны попробовать добавить в свой AppDelegate didFinishLaunchingWithOptions:

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

Это бы получить u [FBSDKAccessToken currentAccessToken] когда пользователь вошел в систему.

и

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

Если этот метод отсутствует в AppDelegate, то он приводит к отмене состояния.

см.:https://developers.facebook.com/docs/ios/getting-started#startcoding


Это может произойти, когда ваше приложение Facebook не имеет разрешения "publish_actions" или вы не используете тестового пользователя.

на Facebook перейдите к управлению приложением, затем убедитесь, что пользователь Facebook, которого вы используете, определен в разделе "роли" как администратор или тестер.

Если это не тестовый пользователь или администратор - Facebook потребует разрешения" publish_actions " для просмотра и утверждения, прежде чем разрешить вашему приложению использовать его, до тех пор вы получите результат" isCancelled=YES".

после тестирования вашего приложения с этим разрешением можно отправить это разрешение на обзор, вам нужно будет загрузить двоичный файл, который демонстрирует использование этого разрешения с точными сведениями о том, как его использовать. После того, как он будет одобрен, вы сможете использовать его с не тестовыми пользователями Facebook.


так как FBSDKLoginKit 4.6.0, то logInWithReadPermissions и logInWithPublishPermissions методы FBSDKLoginManager, похоже, имеют дополнительные fromViewController аргумент и использовать его для представления модалов.

Я звонил logInWithPublishPermissions внутри обратного вызова logInWithReadPermissions, который в этот момент модальный еще не полностью уволен. (Я знаю, что спрашивать разрешения, когда оно не нужно, - плохая практика, но в моем случае, кажется, это правильное место.) Это приводит к сбою с isCancelled равно да. Я добавил некоторые задержки и ждать, пока модальный будет полностью отклонен Исправлена проблема.


У меня была та же проблема, когда я приземлился здесь, оказывается, я использовал только устаревший метод openURL приложения, потому что я тоже использовал Google sign in. Для поддержки iOS 8 и до того, как вам придется реализовать как текущий, так и устаревший метод:

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)
}

устаревшие второй.

Примечание: метод FBSDK добавляется после google с оператором or"||", но порядок не имеет значения, и если вы хотите использовать только метод facebook, просто удалите метод и оператор or.

примечание 2: поскольку swift 3 все еще стабилизирует имя метода, я предлагаю вам всегда использовать автозаполнение из XCode при переопределении и реализации метода делегата.

надеюсь, это поможет o/


этот метод работает в 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);
             }
         }];
    }
}

}

Примечание используйте FBSDKLoginBehaviorWeb вместо FBSDKLoginBehaviorBrowser. Это, безусловно, работает


кроме того, убедитесь, что вы не призываете к FBSDKAccessToken.currentAccessToken внутри didFinishLaunchingWithOptions метод. Настройка в didFinishLaunchingWithOptions необходимо завершить, чтобы маркер мог инициализироваться, прежде чем вы попытаетесь войти в Facebook.


FBSDKLoginManagerLoginResult.isCancelled неожиданно YES:

SDK сообщит об отмене, если пользователь явно нажимает кнопку отмены в диалогах входа в систему или если они вручную переключаются на приложение (известное как неявная отмена). Вы должны убедиться, что вы не инициируете поток входа в систему как часть вашего приложения delegateжизненный цикл (например, запуск входа в систему внутри application:openURL:sourceApplication:annotation:) как будет внешне неявная отмена. Если необходимо, отправьте инициацию входа позже в main очередь, чтобы жизненный цикл делегата приложения завершился первым.


Я тоже столкнулась с той же проблемой и я потратил почти 2 часа, чтобы решить вопрос. То, что я сделал, это

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 

и проблема была устранена

я использовал как Google, так и Facebook login, поэтому мне пришлось реализовать мой метод openURL, как это, 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;
}

/ / вы можете выполнять любые дальнейшие операции с помощью маркера доступа

- (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];
             }
         }];
    } }

(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.уже добавил

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

2.уже добавил

- (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. напишите это заявление [FBSDKProfile enableUpdatesOnAccessTokenChange:YES]; до

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

4.вызовите метод logInWithReadPermissions в dispatch_after (dispatch_time (DISPATCH_TIME_NOW, (int64_t) (1 * NSEC_PER_SEC)), dispatch_get_main_queue (), ^{}


назовите это methord,

FBSDKLoginManager *loginManager = [[FBSDKLoginManager alloc] init];
[loginManager logInWithReadPermissions:@[@"user_friends"] handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
   code
}];