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

Objective c 如何捕获发送到实例异常的无法识别的选择器?,objective-c,ios5,Objective C,Ios5,一段时间后,我将无法识别的选择器发送到实例异常。当我得到这个,我想跳过它,我的应用程序应该工作 然而,我不知道如何捕捉。由于这一点不受欢迎: @property(nonatomic,retain) UIButton *button; @try{ if(button.currentBackgroundImage == nil){//rises exception } }@catch(NSException *e){ } 我该怎么办 谢谢。我经常使用和看到

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

然而,我不知道如何捕捉。由于这一点不受欢迎:

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

       if(button.currentBackgroundImage == nil){//rises exception 
    }
    }@catch(NSException *e){
}
我该怎么办


谢谢。

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

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

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

此外,有时当对象最初是正确的类型,但在解除分配的过程中进行了一半时,会出现此异常。小心


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

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

但是,如果您没有该选项(比如在我的例子中,调用堆栈中的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>
输出:

// 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-26 14:11:04.24650+0100 app[46152:172456]
2019-02-26 14:11:04.246130+0100应用程序[46152:172456]-[NSObject bounds]:未识别的选择器发送到实例0x6000000A6F0
2019-02-26 14:11:04.246226+0100应用程序[46152:172456]捕获
2019-02-26 14:11:04.246242+0100应用程序[46152:172456]最终
2019-02-26 14:11:04.246258+0100应用[46152:172456]再次说明:

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

是,这是正确的。您希望尽可能避免异常^^。经过一段时间后,仍然会得到:-[\uu NSCFType setBackgroundImage:forState:::]:发送到实例的无法识别的选择器。也许有了按钮属性,我应该做点什么。使用此属性,我保存按钮实例,当按下其他按钮时,我将删除以前按下的按钮背景。我打开NSZombie并找到以下内容:-[UIButton setBackgroundImage:forState:]:消息发送到解除分配的实例。有没有可能当我将background设置为nil时,我的按钮被释放了?没有,可能没有,但是你的按钮超出了范围,被释放了。这是另一个问题。如果您使用的是属性分配(即
thing.currentBackgroundImage=img
),则需要检查的@selector是@selector(setCurrentBackgroundImage)