4

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

comrade
  • 4,590
  • 5
  • 33
  • 48
  • set a breakpoint on the line where you `showBanner` and inspect the viewController iVar, to make certain it is indeed an instance of `AdRootViewController`. There could be an issue in appDelegate where you are not assigning the proper object to the property. – YvesLeBorg Jan 16 '17 at 18:55
  • hi, thanks but it is all already checked. The issue isn't reproducible in my own environment. I've added additional checks for nil and `respondsToSelector:` etc. but the issue still exists on some of user's devices. I just surprised that after `respondsToSelector:` can be raised `doesNotRecognizeSelector` exception in such a situation. – comrade Jan 17 '17 at 07:46
  • @comrade I am absolutely sure this cannot happen. I wonder whether `[super onEnterTransitionDidFinish]` can't be the culprit. If you cannot reproduce the issue, you should check whether the user is using current version of your app. – Sulthan Jan 17 '17 at 10:44
  • @Sulthan may be this could be happen. Agree with you. but Sulthan the crash is the only that place so the app version is current and Comrade already checked with break point and the error should tell us that could not find method and Comrade is sure about that this showBanner method has error no other method so what is the issue is quite difficult to find out because its a random crash not for all users. – JAY RAPARKA Jan 17 '17 at 10:57
  • @Sulthan but it happens :). And yes, crash report is for version with provided code. P.S. Just to be clear. Crash report shows exact place where issue is happened. It's line 140 i.e. [viewController showBanner]. – comrade Jan 17 '17 at 12:47
  • @comrade The only thing that comes to my mind is that you are doing some magic tricks with the Obj-C runtime, e.g. overwriting `respondsToSelector`, rewriting `isa`, method swizzling etc. There are really many situations how you could force Obj-C to behave like this. Also, on jailbroken devices there could be some tools to remove ads that could make your app to behave like this. Once I had a situation with a similar error inside my code that was handling in-app purchases and it was caused by some hacking tool on jailbroken devices. – Sulthan Jan 17 '17 at 13:58
  • This can happen especially if you are using an open library for ads that can be easily targetted by ad blockers. – Sulthan Jan 17 '17 at 14:00

2 Answers2

1

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.

Sulthan
  • 128,090
  • 22
  • 218
  • 270
0

whole code looks perfect. so error can not be readable and this is strange that you are checking this respondsToSelector:@selector(showBanner) because in this code there is no need to check that a view controller is able to respond that method because its a object method and it has to call if the view controller not nil so only need to check that a viewController is not nil

so in your code i found something that may be caused this error i don't know how but may be because this is not follow common thing so can you try this for me that it works or not

in your code appDelegate is an NSObject type but in general this is UIResponder type so i just replace NSObject to UIResponder

@interface AppDelegate : UIResponder <UIApplicationDelegate> {
}

Please try this hope this will help you

JAY RAPARKA
  • 1,353
  • 2
  • 13
  • 33