5

一段时间后,我将无法识别的选择器发送到实例异常。当我得到这个时,我想跳过它,我的应用程序应该可以工作。

但是我不知道如何捕捉。因为这没有抓住:

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

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

我怎么能处理这个?

谢谢。

4

3 回答 3

6

我经常使用和看到的技术是:不是捕获异常,而是检查对象是否响应选择器:

if(![button respondsToSelector:@selector(currentBackgroundImage)] || button.currentBackgroundImage == nil) {
  // do your thing here...
}
于 2012-06-21T05:33:04.790 回答
2

如果您遇到此异常,则表示您的代码中存在设计缺陷或错误。通过忽略异常来修补它不是正确的做法。试着找出你为什么要向错误的对象发送错误的消息。您的代码将变得更加健壮和可维护。

此外,有时当对象最初是正确的类型时,您会遇到此异常,但正在释放的过程中途。小心!

如果您仍想绕过异常,请阅读 Apple 的文档,其中解释了在运行时将消息绑定到方法实现的多步骤过程。至少有两个地方可以通过覆盖 NSObject 的默认行为来捕获它。

于 2012-06-21T06:24:35.807 回答
2

我理解告诉您防止无法识别的选择器的答案,因为这是首选方法。

但是在您没有该选项的情况下(例如在我的情况下,Cocoa 内部在调用堆栈的下方混乱)您确实可以在尝试时捕获无法识别的选择器。

概念验证代码:

// 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]);

输出:

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>

如您所见,异常仍记录到控制台,但代码执行仍在继续。

于 2019-02-26T13:17:53.907 回答