Facebook iOS SDK 3.2.1 - [NSError fberrorShouldNot

2019-03-18 09:14发布

问题:

I just upgraded my app from Facebook iOS SDK 3.1 to 3.2.1 and I'm trying to take advantage of the new error handling provided by the new FBError category on NSError. The code is at the bottom. It compiles fine, but when a FB error occurs, I get the following at run time:

- [NSError fberrorShouldNotifyUser]: unrecognized selector sent to instance

This seems like a linker error, where the category is not getting linked in from the the FacebookSDK static library. I tried adding both the -ObjC and -all_load flags under the other linker flags in the target. I read this: http://developer.apple.com/library/mac/#qa/qa1490/ but still no luck.

Basically the same code works fine in the sample projects provided by Facebook. Thanks for any suggestions.

// Open the Facebook session.
- (void)openSession {
    NSArray *permissions = [[NSArray alloc] initWithObjects:@"email", nil];

    // Open or re-open the active session
    [FBSession openActiveSessionWithReadPermissions:permissions
                                   allowLoginUI:YES
                              completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
        [self sessionStateChanged:session state:state error:error];
    }];
}

- (void)handleAuthError:(NSError *)error{
    NSString *alertMessage, *alertTitle;

    if (error.fberrorShouldNotifyUser) {
        // If the SDK has a message for the user, surface it. This conveniently
        // handles cases like password change or iOS6 app slider state.
        alertTitle = @"Something Went Wrong";
        alertMessage = error.fberrorUserMessage;
   } else if (error.fberrorCategory == FBErrorCategoryAuthenticationReopenSession) {
        // It is important to handle session closures as mentioned. You can inspect
        // the error for more context but this sample generically notifies the user.
        alertTitle = @"Session Error";
        alertMessage = @"Your current session is no longer valid. Please log in again.";
   } else if (error.fberrorCategory == FBErrorCategoryUserCancelled) {
        // The user has cancelled a login. You can inspect the error
        // for more context. For this sample, we will simply ignore it.
        NSLog(@"user cancelled login");
    } else {
        // For simplicity, this sample treats other errors blindly, but you should
        // refer to https://developers.facebook.com/docs/technical-guides/iossdk/errors/ for more information.
        alertTitle  = @"Unknown Error";
        alertMessage = @"Error. Please try again later.";
        NSLog(@"Unexpected error:%@", error);
    }

    if (alertMessage) {
        [[[UIAlertView alloc] initWithTitle:alertTitle
                                message:alertMessage
                               delegate:nil
                      cancelButtonTitle:@"OK"
                      otherButtonTitles:nil] show];
    }

}

// Handle Facebook session state changed
- (void)sessionStateChanged:(FBSession *)session
                      state:(FBSessionState)state
                      error:(NSError *)error {
    if (error) {
        [self handleAuthError:error];
    } else {
        switch (state) {
            case FBSessionStateOpen:
                [self onSessionOpen:session];
                break;
            case FBSessionStateOpenTokenExtended:
                [self onSessionOpen:session];
                break;
            case FBSessionStateClosedLoginFailed:
                [self onSessionClose:error];
                break;
            case FBSessionStateClosed:
                // No-op
                // See: https://developers.facebook.com/docs/reference/ios/3.1/class/FBSession
                // Session is closed but token is still cached for later use.
                break;
            default:
                NSLog(@"sessionStateChanged: unknown state: %d", state);
                break;
        }
    }
}

UPDATE: A friend advised that I check if the selector actually exists in the linked binary. I followed the instructions here to find the location of the debug binary in the finder: Where is my application binary in XCode? Then, I right-clicked on MyApp.app and chose "Show Package Contents". Found the binary file (it was the largest file in the list), dragged it into Vim and searched for "fberrorShouldNotifyUser". I couldn't find this selector or any of the FBError selectors. I also tried clearing XCode's derived data - still no luck.

UPDATE #2: Ugh, sometimes you totally miss the obvious answer. It turns out I didn't have the -ObjC flag properly set for my debug builds. See screenshot:

Thanks to d.kendall for getting me to check this again.

回答1:

You need to add -ObjC to "other linker flags" in your project's build settings.



回答2:

Did you install the 3.2.1 sdk into a different directory (rather than overwriting the 3.1 sdk)? If so, it's possible xcode is linking the older version. Can you confirm the framework path in xcode by:

  1. In project navigator where you added the Facebook Framework, right click -> Show in Finder and verify it opens the 3.2.1 sdk location; and,
  2. In your target's build settings, search for "framework" and verify the Framework Search Paths only includes the 3.2.1 sdk path - I have found that it can remember old framework locations and use the the wrong path.