Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 374
Joe Rideout Avatar asked Mar 26 '13 15:03

Joe Rideout


People also ask

How does the Facebook SDK for iOS work with idfas?

The Facebook SDK for iOS only accesses IDFAs in the following scenarios: 1) if your app serves ads within the app through Facebook’s Audience Network, or 2) if your app logs app installs or other mobile App Events in order to attribute those events to your ad campaigns.

How to display nserrors in the Facebook SDK?

The Facebook SDK populates keys defined in FBSDKConstants.h in FBSDKCoreKit.framework in the userInfo dictionary of NSErrors where possible. You should display only the localized messages as errors.

Why am I getting an unrecognized selector sent to instance error?

When using frameworks in Objective-C, classes that use categories to extend existing classes are not loaded automatically. When you try to call a method that has been extended in these classes, you will get an unrecognized selector sent to instance error.

What is the fbsdkapplicationdelegate?

The FBSDKApplicationDelegate is designed to post process the results from Facebook Login or Facebook Dialogs (or any action that requires switching over to the native Facebook app or Safari)


2 Answers

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

like image 83
d.kendall Avatar answered Oct 20 '22 10:10

d.kendall


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.
like image 1
Chris Pan Avatar answered Oct 20 '22 12:10

Chris Pan