ユーザーをアプリにログインする方法がわかりません。 [FBSDKAccessToken currentAccessToken]
はnilなので、私は次のように呼び出しています:
[[[FBSDKLoginManager alloc] init] logInWithPublishPermissions:@[@"publish_actions"] handler:…];
含まれているサンプルプロジェクトごと。これによりFacebookアプリに切り替わりますが、メッセージには「既に承認済みですアプリ名。」と表示されます。 [OK]をクリックすると、アプリに戻りますが、grantedPermissions
とdeclinedPermissions
は両方とも結果でnil
であり、isCancelled
はYES
です。 [FBSDKAccessToken currentAccessToken]
は、まだnil
です。
currentAccessToken
をどのように埋めるかを理解することはできません。logInWithPublishPermissions
への呼び出しがそれを行う必要があるようですが、そうではありません。
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では、アプリが使用を許可する前に、「isCancelled = YES」という結果を受け取るまで、「publish_actions」権限を確認および承認する必要があります。
この許可を使用してアプリをテストした後、レビューのためにこの許可を送信することができます。この許可の使用方法を示すバイナリをアップロードする必要があります。承認されると、テスト以外のFacebookユーザーと使用できるようになります。
私がここに着いたときに同じ問題がありましたが、私もGoogleサインインを使用していたため、非推奨のアプリケーションopenURLメソッドのみを使用していたことがわかりました。 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)
}
非推奨は2番目です。
注:FBSDKメソッドは、または「||」でgoogleの後に追加されます演算子ですが、順序は関係ありません。facebookメソッドのみを使用する場合は、メソッドとor演算子を消去します。
注2:As Swift 3メソッド名の安定化は変更される可能性があります。デリゲートのメソッドをオーバーライドおよび実装する場合は、常にXCodeのオートコンプリートを使用することをお勧めします。
これがo /
FBSDKLoginKit 4.6.0以降、FBSDKLoginManagerのlogInWithReadPermissions
およびlogInWithPublishPermissions
メソッドには追加のfromViewController
引数があり、それを使用してモーダルを表示するようです。
logInWithPublishPermissions
のコールバック内でlogInWithReadPermissions
を呼び出していましたが、その時点でモーダルはまだ完全に却下されていません。 (必要のないときに許可を求めるのは悪い習慣だと思いますが、私の場合はこれが適切な場所のようです。)これにより、isCancelled
がYESになって失敗します。いくつかの遅延を追加し、モーダルが完全に却下されるのを待って問題を修正しました。
この方法は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 [〜#〜]:FBSDKLoginBehaviorBrowserの代わりにFBSDKLoginBehaviorWebを使用します。これは確かに動作します
(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.dispatch_after(dispatch_time(DISPATCH_TIME_NOW、(int64_t)(1 * NSEC_PER_SEC)))、dispatch_get_main_queue()、^ {}でlogInWithReadPermissionsメソッドを呼び出します
FBSDKLoginManagerLoginResult.isCancelled
は予期せずYES
:
ユーザーがログインダイアログでキャンセルボタンを明示的にタップした場合、またはアプリを手動でアプリに切り替えた場合(暗黙的なキャンセルと呼ばれる)、SDKはキャンセルを報告します。アプリdelegate
のライフサイクルの一部としてログインフローを開始していないことを確認する必要があります(application:openURL:sourceApplication:annotation:
)それは暗黙的なキャンセルを模倣します。必要に応じて、アプリのデリゲートのライフサイクルが最初に完了するように、後でログイン開始をメインキューにディスパッチします。
また、didFinishLaunchingWithOptions
メソッド内でFBSDKAccessToken.currentAccessToken
を呼び出していないことを確認してください。 Facebookにログインする前にトークンを初期化できるように、didFinishLaunchingWithOptions
のセットアップを完了する必要があります。
私も同じ問題に直面し、問題を解決するためにほぼ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の両方のログインを使用していたので、このような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];
}
}];
} }