你能发一条消息说对象不会被抓住吗?

时间:2014-05-16 19:20:21

标签: objective-c

我正在读这本书,它说这段代码会编译但会导致运行时异常。但是当我在我的计算机上运行它时,它无法编译:“没有已知的实例方法......”

#import "Fraction.h"
int main (int argc, char * argv[])
{
     @autoreleasepool {
     Fraction *f = [[Fraction alloc] init];
     [f noSuchMethod];
     }
   return 0;
}

我的问题是这样做会导致运行时异常,何时会导致编译时警告?

2 个答案:

答案 0 :(得分:2)

编译时错误是因为选择器noSuchMethod没有出现在编译器看到的任何类上。在ARC下,编译器无法在这种情况下安全地决定如何应用内存管理规则(它可能会尝试遵循标准命名约定,但如果在某些其他头中使用备用语义声明选择器,则可能导致极其困难的错误)。它几乎肯定是一个错误,所以编译器正确地猜测。 (还有另一个与返回类型相关的问题,在ARC之前,编译器会猜测它,但它通常不是你想要的,即使它恰好在大多数时候都是猜测的。)

如果已知{em>某些类而不是-noSuchMethod存在Fraction,则编译器会发出警告。在运行时,如果f未能响应,则会出现运行时异常。(这是旧的行为;似乎clang可能在我的实验中变得更加严格并且会抛出一个现在在这种情况下也会出现错误。如果您的书在更改之前写过,或者作者暂时没有重新检查,这可能会与您的书混淆。)

如果知道noSuchMethod存在,但f被声明为id类型,则不会生成警告。在运行时,如果f未能响应,则会出现运行时异常。

答案 1 :(得分:1)

这取决于......

当您使用ARC时,默认情况下,当编译时未知方法名称时,编译器将为方法调用引发错误。 如果不使用ARC,则仅在编译时收到警告。

但是,您可以在两种情况下自定义要传递的编译器的警告/错误级别。

Objective-C在运行时绑定方法调用。如果您设法将其编译,那么您甚至可以在抛出异常之前对运行时错误作出反应,并在运行期间以noSuchMethod的名义动态注册方法,并在调用方法时实际执行某些代码。同一运行时会话期间的未来。可能是在运行时动态绑定的这种行为,你的书的autor试图通过示例来解释。