10

我想在我的应用程序中加入一些 Facebook 集成。在这一点上,我已经成功登录,发布到朋友墙,检索朋友列表等。除了一件事,一切都很好......

如果用户从您的 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

5

我发现这也发生在我自己身上......当用户更改他们的 Facebook 密码时发现它,我们无法再进行身份验证。手动重新同步/清除帐户会话允许他们再次登录。

-(void)syncFacebookAccount
 {
    [self forceLogout];
    ACAccountStore *accountStore = [[ACAccountStore alloc] init];
    ACAccountType *accountTypeFB = [accountStore         accountTypeWithAccountTypeIdentifier:@"com.apple.facebook"];
    if (accountStore && accountTypeFB) {
    NSArray *fbAccounts = [accountStore accountsWithAccountType:accountTypeFB];
    id account;
    if (fbAccounts && [fbAccounts count] > 0 && (account = [fbAccounts objectAtIndex:0])) {
    [accountStore renewCredentialsForAccount:account completion:^(ACAccountCredentialRenewResult renewResult, NSError *error) {
                    // Not actually using the completion handler...
    }];
            }
        }
    }
于 2013-05-04T07:20:18.397 回答
3

实际上很难解析和检测这些类型的错误,原因有两个:

  1. 在您实际尝试并失败 FBRequest (或类似的)之前,我无法找出任何方法来检测此问题,并且
  2. NSError从失败传递的对象FBRequest非常难以以任何功能方式解析和使用。

下面是我写的疯狂的方法,同时通宵达旦地处理这个问题。它处理NSError *error来自失败FBRequest尝试的对象,并将其传递给相关方法或显示我能找到的最明智的错误(或击中底部的全部错误)。

请注意评论 - 特别是围绕innerErrorparsedResponse- 详细说明我到目前为止发现的内容。祝你好运,勇敢的士兵:

- (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

我有同样的问题,在 Facebook SDK 网站上找不到有关错误代码的正确文档。

[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 回答