简体   繁体   English

如何捕获发送到实例异常的无法识别的选择器?

[英]How to catch unrecognized selector sent to instance exception?

I am getting after some time unrecognized selector sent to instance exception. 经过一段时间后,我发现无法识别的选择器被发送到实例异常。 When i get this i want just skip it and my app should work. 当我得到这个,我想跳过它,我的应用程序应该工作。

However i don't know how to catch. 但是我不知道该怎么抓。 As this don't catch: 因为这没有抓住:

@property(nonatomic,retain) UIButton *button;
    @try{

       if(button.currentBackgroundImage == nil){//rises exception 
    }
    }@catch(NSException *e){
}

How i could handle this ? 我怎么能处理这个?

Thanks. 谢谢。

The technique I use and see often is: instead of catching the exception, check if the object responds to the selector: 我经常使用和查看的技术是:检查对象是否响应选择器,而不是捕获异常:

if(![button respondsToSelector:@selector(currentBackgroundImage)] || button.currentBackgroundImage == nil) {
  // do your thing here...
}

If you are getting this exception, it means there is a design flaw, a bug in your code. 如果您收到此异常,则表示存在设计缺陷,即代码中存在错误。 Patching it by ignoring the exception is not the right thing to do. 通过忽略异常来修补它不是正确的做法。 Try to pin down why you are sending the wrong message to the wrong object instead. 尝试确定将错误消息发送到错误对象的原因。 Your code will become more robust and maintainable. 您的代码将变得更强大和可维护。

Also, sometimes you get this exception when the object originally was of the right type, but is halfway in the process of being deallocated. 此外,有时当对象最初是正确的类型时,你会得到这个异常,但是在被解除分配的过程中已经过了一半。 Watch out! 小心!

If you still want to bypass the exception, read Apple's docs where it explains the multi-step process by which messages are bound to method implementations at run time. 如果您仍想绕过异常,请阅读Apple的文档,其中解释了在运行时将消息绑定到方法实现的多步骤过程。 There is at least two places where you can catch it by overriding NSObject's default behavior. 至少有两个地方可以通过覆盖NSObject的默认行为来捕获它。

I understand the answers telling you to prevent the unrecognized selector since that is the preferred method. 我理解答案告诉你要阻止无法识别的选择器,因为这是首选的方法。

But in the case where you do not have that option (such as in my case, Cocoa internals messing up further down the call stack) you can indeed catch the unrecognized selector as you tried. 但是在你没有这个选项的情况下(例如在我的情况下,Cocoa内部会在调用堆栈中进一步搞乱)你可以在尝试时捕获无法识别的选择器。

Proof of concept code: 概念证明代码:

// Do a really bad cast from NSObject to NSButton
// to get something to demonstrate on
NSButton *object = (NSButton*)[[NSObject alloc] init];

@try{
    // Log the description as the method exists 
    // on both NSObject and NSButton
    NSLog(@"%@", [object description]);

    // Send an unrecognized selector to NSObject
    [object bounds];
} @catch(NSException *e){
    NSLog(@"Catch");
} @finally {
    NSLog(@"Finally");
}

// Print the description to prove continued execution
NSLog(@"Description again: %@", [object description]);

Output: 输出:

2019-02-26 14:11:04.246050+0100 app[46152:172456] <NSObject: 0x60000000a6f0>
2019-02-26 14:11:04.246130+0100 app[46152:172456] -[NSObject bounds]: unrecognized selector sent to instance 0x60000000a6f0
2019-02-26 14:11:04.246226+0100 app[46152:172456] Catch
2019-02-26 14:11:04.246242+0100 app[46152:172456] Finally
2019-02-26 14:11:04.246258+0100 app[46152:172456] Description again: <NSObject: 0x60000000a6f0>

As you can see the exception is still logged to the console, but the code execution continues. 如您所见,异常仍记录到控制台,但代码继续执行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM