FBSDKLoginManager logInWithPublishPermissions siempre devuelve isCancelled = YES

Tengo problemas para descubrir cómo registrar un usuario en mi aplicación. [FBSDKAccessToken currentAccessToken] es nulo, entonces estoy llamando:

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

según el proyecto de muestra incluido. Esto cambia a la aplicación de Facebook, pero el mensaje dice “Ya has autorizado el nombre de la aplicación “. Hago clic en Aceptar y vuelve a entrar en la aplicación, pero grantedPermissions y grantedPermissions son nil en el resultado, y está isCancelled es YES . [FBSDKAccessToken currentAccessToken] sigue siendo nil .

No puedo entender cómo se supone que currentAccessToken completar currentAccessToken . Me parece que la llamada a logInWithPublishPermissions debería hacer eso, pero no es así.

Debería intentar agregar en su AppDelegate didFinishLaunchingWithOptions:

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

Esto te pondría a [FBSDKAccessToken currentAccessToken] cuando el usuario haya iniciado sesión.

y

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

Si este método no está presente en AppDelegate, resulta en estado cancelado.

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

Esto puede suceder cuando su aplicación de Facebook no tiene el permiso “publish_actions” o no está utilizando un usuario de prueba .

En Facebook, ve a administrar tu aplicación, luego asegúrate de que el usuario de Facebook que estás utilizando esté definido en “Roles” como administrador o tester.

Si no es un usuario o administrador de prueba: Facebook requerirá que se revise y apruebe el permiso “publish_actions” antes de permitir que su aplicación lo use, hasta entonces recibirá un resultado “isCancelled = YES”.

Después de probar su aplicación con este permiso, es posible enviar este permiso para su revisión, deberá cargar un archivo binario que demuestre el uso de este permiso con detalles exactos sobre cómo usarlo. Después de su aprobación, podrá usarlo con usuarios de Facebook que no sean de prueba.

Desde FBSDKLoginKit 4.6.0, los métodos logInWithReadPermissions y logInWithPublishPermissions de FBSDKLoginManager parecen tener un argumento adicional fromViewController y lo usan para presentar modals.

Estaba llamando a logInWithPublishPermissions dentro de la callback de logInWithReadPermissions , que en ese momento el modal aún no se ha descartado por completo . (Sé que es una mala práctica pedir permiso cuando no es necesario, pero en mi caso este parece ser el lugar correcto para hacerlo). Esto causa que falle con isCancelled es igual a YES. Agregué un poco de retraso y esperé a que el modal fuera completamente descartado solucionó el problema.

Tuve el mismo problema cuando aterricé aquí, resulta que solo estaba usando el método obsoleto de la aplicación openURL porque también estaba usando el inicio de sesión de Google. Para admitir iOS 8 y antes, debe implementar el método actual y el método en desuso:

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

El obsoleto es el segundo.

Nota: El método FBSDK se agrega después de google con un o “||” operador, pero el orden no importa y si solo quiere utilizar el método facebook simplemente borre el método y el operador o.

Nota 2: como swift 3 sigue estabilizándose, el nombre del método puede cambiar. Le sugiero que siempre use el autocompletado de XCode al anular e implementar el método de un delegado.

Espero que esto ayude o /

Este método funciona en 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); } }]; } } 

}

NOTA : utilice FBSDKLoginBehaviorWeb en lugar de FBSDKLoginBehaviorBrowser . Esto seguramente funcionará

Además, asegúrese de no llamar a FBSDKAccessToken.currentAccessToken DENTRO de su método didFinishLaunchingWithOptions . La configuración en didFinishLaunchingWithOptions debe completarse para que el token pueda inicializarse antes de intentar iniciar sesión en Facebook.

FBSDKLoginManagerLoginResult.isCancelled es inesperadamente YES :

El SDK informará una cancelación si el usuario toca de forma explícita un botón de cancelar en los cuadros de diálogo de inicio de sesión, o si la aplicación vuelve a su aplicación manualmente (lo que se conoce como cancelación implícita). Debe asegurarse de no iniciar un flujo de inicio de sesión como parte del ciclo de vida de su delegate aplicaciones (como iniciar un inicio de sesión dentro de la application:openURL:sourceApplication:annotation: ya que eso imitará una cancelación implícita. Si es necesario, envíe la iniciación de inicio de sesión más tarde a la cola principal para que el ciclo de vida del delegado de la aplicación se complete primero.

También enfrenté el mismo problema y pasé casi 2 horas para resolver el problema. Lo que hice es

 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 

y el problema fue arreglado

Estaba usando tanto el inicio de sesión de google como el de Facebook, así que tuve que implementar mi método openURL de esta manera, iOS 9+

 - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)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; } 

// puedes realizar más operaciones usando el token de acceso

 - (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 *)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 ya agregado

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

2.check ya agregado

 - (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. escriba esta statement [FBSDKProfile enableUpdatesOnAccessTokenChange:YES]; antes de

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

4.call método logInWithReadPermissions en dispatch_after (dispatch_time (DISPATCH_TIME_NOW, (int64_t) (1 * NSEC_PER_SEC)), dispatch_get_main_queue (), ^ {}

llama este methord,

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