Unrecognized selector sent to instance when assigning a block property

776 views Asked by At

I have an app that may require the user to authenticate during navigation. If this is the case, I'd like the login event to return a callback back to the operation that requested the login event, for it to know that the login was either successful or not.

For example, a method that requires authentication will prompt for credentials by calling the methods of a helper class:

[UserModel promptCredentials:^(NSHTTPURLResponse *response) {
    if (response.statusCode == 200) {
        [self userWillComment:userActionCell];
    }
 }];

The helper method instantiates the login view controller, and tries to set the callback property:

+ (void) promptCredentials:(void (^)(NSHTTPURLResponse *response))callback{

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    UIViewController *currentViewController = [[UIApplication sharedApplication] keyWindow].rootViewController;
    LoginViewController *loginScreenNav = [storyboard instantiateViewControllerWithIdentifier:@"LoginNavigationController"];
    loginScreenNav.loginCallback = callback;
    if([currentViewController isKindOfClass:[UINavigationController class]]){
        currentViewController = [(UINavigationController *)currentViewController visibleViewController];
    } else if(currentViewController.presentedViewController){
        currentViewController = currentViewController.presentedViewController;
    }

    dispatch_async(dispatch_get_main_queue(), ^{
        [currentViewController presentViewController:loginScreenNav animated:YES completion:nil];
    });
}

The Login view controller has the following property defined in its interface:

@property (nonatomic, strong) void (^loginCallback)(NSHTTPURLResponse *response);

When the login takes place within the 'LoginViewController', I am trying to execute the callback, like this:

if (self.loginCallback != nil) {
    self.loginCallback(response);
}

However, when this code runs, the line within the helper method loginScreenNav.loginCallback = callback; makes the app crash with error:

-[UINavigationController setLoginCallback:]: unrecognized selector sent to instance

Essentially, I need some guidance on how to correctly assign this property block within the login view controller so it can get executed after the login network operation takes place.

1

There are 1 answers

1
matt On BEST ANSWER

The reason for the crash is that you are lying to yourself (and the compiler) in this line:

LoginViewController *loginScreenNav = [storyboard instantiateViewControllerWithIdentifier:@"LoginNavigationController"];

You have instantiated a view controller from the storyboard, yes; but it is not a LoginViewController. It is a UINavigationController. Examine your storyboard carefully, look at the view controller that is marked with the "LoginNavigationController" identifier, and you will see that this is true.