Search code examples
iosobjective-ccocos2d-iphonecrashrespondstoselector

doesNotRecognizeSelector error after respondsToSelector check


Short description: I get doesNotRecognizeSelector error when call method on object that definitely has this method and it happens after calling respondsToSelector.

It's a very strange situation and I didn't understand how it can be :). I saw this error in logs on some of user devices but not on all of them. I can't repeat this on my own device.

I'm trying to figure out how it can happen and added condition with respondsToSelector but issue takes place again.

Some code bellow. Hope it helps

1) I've viewController object in AppDelegate.

@interface AppDelegate : NSObject <UIApplicationDelegate> {
}
@property (nonatomic, retain) AdRootViewController *viewController;
...
@end

@implementation AppDelegate
@synthesize viewController;
...
@end

2) In other class I'm trying to get this object and call one of its methods. But on [viewController showBanner] call all fails with doesNotRecognizeSelector error.

- (void) onEnterTransitionDidFinish {
    [super onEnterTransitionDidFinish];

    AdRootViewController *viewController = [(AppDelegate *)[[UIApplication sharedApplication] delegate] viewController];
    if (viewController != nil && [viewController respondsToSelector:@selector(showBanner)]) {
        [viewController showBanner];
    }
}

3) AdRootViewController has this method and it's declared in interface.

@interface AdRootViewController : UIViewController {
}
- (void)showBanner;
...
@end

@implementation AdRootViewController
...
- (void)showBanner
{
    adBannerViewIsVisible = YES;
    ...
}
...
@end

The failed string of code is [viewController showBanner].

Error log looks like this:

1 CoreFoundation __exceptionPreprocess + 1245624
2 libobjc.A.dylib objc_exception_throw + 34136
3 CoreFoundation -[NSObject(NSObject) doesNotRecognizeSelector:] + 1274468
4 CoreFoundation ___forwarding___ + 1262188
5 CoreFoundation _CF_forwarding_prep_0 + 186376
6 <project_id> 4296487336 + 487848
...

P.S. May be stack trace will show it better: enter image description here


Solution

  • I realized there is one very rare situation in which this situation can happen.

    On jailbroken devices, there are many tools that can cause this. E.g. a tool to show content that is hidden behind in-app purchases or a tool to hide ads.

    Those tools usually target open libraries for in-app purchases or ads. If you use such a library, the tool will just replace the implementation of your class by its own implementation that is made to override your functionality - behave like everything has been already paid or remove the methods that show ads (for an example, see http://www.tenorshare.com/guide/how-to-block-ads-on-iphone-ipad-ipod.html)

    I have found at least two open libraries that use class AdRootViewController. That means such a tool will try to replace the implementation of your class, in the process also removing method showBanner.

    You can only check whether those crash reports come from jailbroken devices (if you are not using crashlytics or similar crash reporting library, use it).

    If you know the error is present only on jailbroken devices, ignore it. It's caused by the user when trying to remove your ads.