10

アプリに Facebook を統合したいと考えています。この時点で、ログイン、フレンド ウォールへの投稿、フレンド リストの取得などを行うことができました。1 つのことを除いてすべて問題ありません...

ユーザーがFacebook 設定/アプリケーションからアプリを削除してから iOS アプリに入ると、コードは Facebook アプリがユーザー設定から削除されたことを認識せず、ログインしていると想定します (これは問題です。ユーザーが友達のウォールに投稿しようとしても、アプリは何もしません)。

その後、ユーザーは iOS アプリを閉じて再起動します。この再起動により、iOS アプリは「修正」され、ユーザーがログインしていないことが検出されます。

ログインフローをユーザーにもたらすために、ユーザーがFacebookアプリを設定から削除した直後の瞬間を検出することができません...

これが私のコードです:

アプリの最初のシーンで...

if([FBSession activeSession].state == FBSessionStateCreatedTokenLoaded)
{
    NSLog(@"Logged in to Facebook");
    [self openFacebookSession];
    UIAlertView *alertDialog;

    alertDialog = [[UIAlertView alloc] initWithTitle:@"Facebook" message:@"You're already logged in to Facebook" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];

    [alertDialog show];

    [alertDialog release];
    return YES;
}
else{
    NSLog(@"Not logged in to Facebook"); //Show the login flow
    return NO;
}

openFacebookSession のコードは次のとおりです。

-(void)openFacebookSession
{
    NSArray *permissions = [[NSArray alloc] initWithObjects:
                            @"publish_stream",
                            nil];

    [FBSession openActiveSessionWithPublishPermissions:permissions defaultAudience:FBSessionDefaultAudienceFriends allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
        [self sessionStateChanged:session state:status error:error];
    }];
}

sessionStateChanged のコード...

-(void)sessionStateChanged:(FBSession *)session state:(FBSessionState)state error:(NSError *)error
{
    switch (state) {
        case FBSessionStateOpen: {
            NSLog(@"Session opened");
        }
            break;
        case FBSessionStateClosed:
        case FBSessionStateClosedLoginFailed:
            [FBSession.activeSession closeAndClearTokenInformation];
            break;
        default:
            break;
    }

    if (error) {
        UIAlertView *alertView = [[UIAlertView alloc]
                                  initWithTitle:@"Error"
                                  message:error.localizedDescription
                                  delegate:nil
                                  cancelButtonTitle:@"OK"
                                  otherButtonTitles:nil];
        [alertView show];
    }
}

どうもありがとうございました!

4

3 に答える 3

3

これらのタイプのエラーを解析して検出することは、次の 2 つの理由から実際には非常に困難です。

  1. あなたが実際に FBRequest (または類似のもの) を試みて失敗するまで、この問題を検出する方法を見つけることはできません。
  2. 失敗したNSErrorオブジェクトから渡されたオブジェクトはFBRequest、機能的な方法で解析して使用するのが非常に困難です。

以下は、これに対処するために文字通り徹夜をしながら書いたクレイジーな方法です。NSError *error失敗した試行からオブジェクトを処理し、FBRequestそれを関連するメソッドに渡します。または、見つけた最も賢明なエラーを表示します (または、一番下のキャッチオールにヒットします)。

innerError特にとの周りのコメントに注意してくださいparsedResponse。これは、私がこれまでに発見したことを詳述しています。がんばれ、勇敢な兵士:

- (void)handleFacebookError:(NSError *)error
         withPermissionType:(RMFacebookPermissionsType)type // this is just a typedef enum specifying Write or Read permissions so I can react accordingly
             withCompletion:(void (^)(BOOL retry))completionBlock {

    newMethodDebugLog;
    NSParameterAssert(error);
    NSParameterAssert(type);
    NSParameterAssert(completionBlock); //  the completion block tells the controller whether the error is 'fatal' or can be recovered - if YES, it can be recovered

    // this is the parsed result of the graph call; some errors can appear here, too, sadly
    NSDictionary *parsedResponse = [error.userInfo objectForKey:@"com.facebook.sdk:ParsedJSONResponseKey"];
    int parsedErrorCode = [[[[parsedResponse objectForKey:@"body"]
                             objectForKey:@"error"]
                            objectForKey:@"code"]
                           intValue];

    // this is an instance of NSError created by Facebook; it contains details about the error
    NSError *innerError = [error.userInfo objectForKey:@"com.facebook.sdk:ErrorInnerErrorKey"];

    // innerError is usually un-recoverable
    if (innerError) {

        // innerError seems to be the response given in true HTTP problems;
        DebugLog(@"______innerError FOUND______");
        DebugLog(@"innerError: %@",innerError);
        DebugLog(@"innerError.code: %d",innerError.code);

        // digging deep enough, you can actually find a coherent error message! :D
        DebugLog(@"innerError.localizedDescription: %@",innerError.localizedDescription);

        if (![alert isVisible]) {

            NSString *errorString = @"Facebook Connection Failed";

            NSString *okString = @"OK";

            alert = [[UIAlertView alloc] initWithTitle:errorString
                                               message:innerError.localizedDescription
                                              delegate:nil
                                     cancelButtonTitle:okString
                                     otherButtonTitles:nil];

            [alert show];

        } else {

            DebugLog(@"Alert already showing!");

        }

        completionBlock(NO);

    } else if (parsedResponse &&
               parsedErrorCode != 2) { // I honestly forget what error 2 is.. documentation fail :(

        // parsedResponses can usually be recovered
        DebugLog(@"parsed response values: %@",[parsedResponse allValues]);

        switch (parsedErrorCode) {
            case 2500:
            case 200:
            case 190:
            {
                DebugLog(@"parsedError code hit! forcing re-login.");

                // all errors in case 190 seem to be OAuth issues
                // http://fbdevwiki.com/wiki/Error_codes#Parameter_Errors
                // if needed, "error_subcode" 458 == user has de-authorized your app
                // case 2500 reported while grabbing from a photo album & not logged in
                // case 200 "requires extended permission: publish_actions"

                if (type == RMFacebookPermissionsTypeRead) {

                    [self _getFacebookReadPermissionsWithUI:YES
                                                 completion:completionBlock];

                } else if (type == RMFacebookPermissionsTypeWrite) {

                    [self _getFacebookWritePermissionsWithUI:YES
                                                  completion:completionBlock];

                }

                break;
            }

            default:
                completionBlock(YES);
                break;
        }

    } else {

        if (![alert isVisible]) {

            NSString *errorString = @"Facebook Error";

            NSString *messageString = @"Mixture Photos was unable to connect to Facebook on your behalf. This is usually a temporary problem. Please try again later.";

            NSString *okString = @"OK";

            alert = [[UIAlertView alloc] initWithTitle:errorString
                                               message:messageString
                                              delegate:nil
                                     cancelButtonTitle:okString
                                     otherButtonTitles:nil];

            [alert show];

        } else {

            DebugLog(@"Alert already showing!");

        }

        completionBlock(NO);

    }
}
于 2012-12-25T11:09:28.157 に答える
0

同じ問題があり、FacebookSDKサイトでエラーコードに関する適切なドキュメントを見つけることができませんでした。

[error code];orの[error userInfo];値を比較して問題を解決しました。

セッションには状態がFBSessionStateClosedLoginFailedあり、エラーのuserInfoディクショナリは次の形式になります

"com.facebook.sdk:ErrorLoginFailedReason" = "com.facebook.sdk:ErrorLoginFailedReason";

一方、エラーコードは2、sessionStateChanged:::関数の最後に処理できるように表示されます

- (void)sessionStateChanged:(FBSession *)session
                  state:(FBSessionState)state
                  error:(NSError *)error {
switch (state) {
    case FBSessionStateOpen: {
        //update permissionsArrat
        [self retrieveUSerPermissions];

        if (!needstoReopenOldSession) {
            //First User information
            [self getUserInformation:nil];
        }

        NSNotification *authorizationNotification = [NSNotification notificationWithName:facebookAuthorizationNotification object:nil];
        [[NSNotificationCenter defaultCenter] postNotification:authorizationNotification];

    }
    case FBSessionStateClosed: {
        break;
    }
    case FBSessionStateClosedLoginFailed: {
        [FBSession.activeSession closeAndClearTokenInformation];
        break;
    }
    default:
        break;
}

if (error) 
{
    NSNotification *authorizationNotification = [NSNotification  notificationWithName:faceBookErrorOccuredNotification object:error];
    [[NSNotificationCenter defaultCenter] postNotification:authorizationNotification];
}
}
于 2012-10-15T08:57:20.200 に答える