Facebook iOS SDK 3.2.1 - [NSError fberrorShouldNotifyUser]: unrecognized selector sent to instance
Asked Answered
F

2

12

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:

Missing ObjC Flag

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

Flagwaving answered 26/3, 2013 at 15:7 Comment(0)
D
18

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

Dugaid answered 4/4, 2013 at 16:53 Comment(5)
Thanks for the suggestion - I already tried both -ObjC and -all_load in "other linker flags", but I'm still stuck.Flagwaving
Ok - thanks for getting me to check this again. It turns out I had the flag set for Debug and Release, but not under a sub-tab of Release titled "Any Architecture | Any SDK". Ugh, can't believe I missed this before. Thanks!!!!Flagwaving
Could you please explain why it helped ?Militant
this has fixed an issue for me but I would also like to know why?Educational
please note that adding the -ObjC could raise the app's sizeDogvane
S
1

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.
Stephine answered 1/4, 2013 at 18:22 Comment(1)
Thanks for the help! 1. Verified - It's pointing to the the 3.2.1 sdk location. 2. Framework Search Paths look like this: $(inherited), "$(SRCROOT)". I trashed the old copy of 3.1 before installing 3.2.1. Also, my code is using the new 3.2.1 FBWebDialogs stuff which I assume wouldn't work if xcode was linking in the older version?Flagwaving

© 2022 - 2024 — McMap. All rights reserved.