【问题标题】:How to enable exception handling in objective-c and xcode如何在objective-c和xcode中启用异常处理
【发布时间】:2010-06-30 07:59:35
【问题描述】:

编辑:问题已解决(部分):这是一个模拟器错误。我已经在两个装有 iOS 3.1.3 和 4.0 的设备上编译和测试了它。异常处理正确。小心,模拟器是你的敌人!

这快把我逼疯了。我不知道如何在我的项目中启用异常处理。查看下面的代码和调试器输出。

我的目标是捕获异常,而不是更正代码以便处理异常并且应用不会崩溃。

我正在使用 XCode 3.2.3,iPhone SDK 4 final。我刚刚创建了一个简单的基于视图的 iPhone 应用程序来测试它。

我查看了我的项目设置,是的,“启用 Objective-C 异常”开关已被选中。我正在使用 GCC 4.2。

当我详细查看构建过程时,编译器标志 -fno-objc-exceptions 不在参数列表中!

我在这里错过了什么?

提前致谢 尼克

NSArray * foo = [[NSArray alloc] init];

@try {
   NSLog(@"trying...");  
   [foo objectForKey:@"yeah"];
}
@catch (NSException * e) {
   NSLog(@"catching %@ reason %@", [e name], [e reason]);
}
@finally {
   NSLog(@"finally");
}

导致

trying...

-[__NSArrayI objectForKey:]: unrecognized selector sent to instance 0x5d5f780

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI objectForKey:]: unrecognized selector sent to instance 0x5d5f780'

*** Call stack at first throw:
(
 0   CoreFoundation                      0x02393919 __exceptionPreprocess + 185
 1   libobjc.A.dylib                     0x024e15de objc_exception_throw + 47
 2   CoreFoundation                      0x0239542b -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
 3   CoreFoundation                      0x02305116 ___forwarding___ + 966
 4   CoreFoundation                      0x02304cd2 _CF_forwarding_prep_0 + 50
...
)
terminate called after throwing an instance of 'NSException'

是否到达了 catch 块和 finally 块。

【问题讨论】:

    标签: iphone objective-c xcode gcc exception-handling


    【解决方案1】:

    来自How do I catch global exceptions? 的引用: “objc_exception_throw 不是异常。它是引发 Objective-C 异常的函数。同样,EXC_ARITHMETIC 不是 Objective-C 异常;它是 Mach(内核)异常,这意味着您的应用程序试图做某事完全无效。- Peter Hosey 5 月 14 日 9:14"

    该线程确实有一个链接到您的问题的解决方案,但它似乎出现了。该链接指向http://www.restoroot.com/Blog/2008/10/20/crash-reporter-for-iphone-applications-part-2/,这看起来有点冒险,但如果它有效,对你来说可能是值得的。

    有与此相关的错误报告,例如:http://www.openradar.me/8081169(本月早些时候发布)

    (已更新以总结来自以下 cmets 的信息。)

    【讨论】:

    • 感谢我正在调查的帖子。
    • 我不明白的是:在这种情况下有一个异常:NSInvalidArgumentException,它被声明为未捕获,它是 NSException 的一个实例。因此,似乎存在某种无法捕获的异常。向对象的实例发送未知消息在objective-c这样的动态语言中应该是常见的情况,那么如何处理这样的异常呢?
    • 这很好。你看过NSSetUncaughtExceptionHandler吗?例如。 stackoverflow.com/questions/1282364/iphone-exception-handling
    • 是的,我做到了。 Apple 文档在此“设置顶级错误处理功能,您可以在程序终止之前执行最后一分钟的日志记录”。该应用程序不应终止:)
    • 感谢 Kalle,它看起来确实像一个错误。其实有点难过。
    【解决方案2】:

    如果我理解你的问题是正确的。

    您的 Try/catch 块工作正常。

    它正在尝试运行您的代码,并捕获一个错误。 您需要决定当它在块中捕获错误和代码时要做什么。 我通常在 CATCH 部分这样做。因为无论是否抛出异常,finally 位都会执行。

    【讨论】:

    • 示例代码只是一个简单的场景来强制一个应该被捕获的异常。
    • 我认为因为你的 NSArray 是空的,你不会看到错误,因为总是返回 nil。
    • 试试这个,NSArray * foo = [NSArray arrayWithObjects:@"yeah", @"yeah1", nil];而不是 NSArray * foo = [[NSArray alloc] init];
    • 你弄错了。我想要这个例外。这与处理 NSArray 无关。这是关于处理如果您将消息发送到它无法识别的对象时引发的异常。
    • 是的,在我发布答案后,我意识到您正在尝试强制错误,当我第一次运行您的代码时,我没有收到任何错误返回?我现在这样做了,这意味着我做了一些奇怪的事情!诚然,我对您期望发生的事情感到困惑。
    【解决方案3】:

    您的示例代码正在捕获 NSException 异常,但不是正在抛出的异常 NSInvalidArgumentException。如果您寻找那个特定的例外,您可能会有更好的运气。

    NSArray * foo = [[NSArray alloc] init];
    
    @try {
       NSLog(@"trying...");  
       [foo objectForKey:@"yeah"];
    }
    @catch (NSInvalidArgumentException *e) {
       NSLog(@"Invalid argument called.");
    }
    @catch (NSException * e) {
       NSLog(@"catching %@ reason %@", [e name], [e reason]);
    }
    @finally {
       NSLog(@"finally");
    }

    不过,我现在没有任何方法可以自己测试它。

    更多信息请参见http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocExceptionHandling.html

    【讨论】:

    • 这不会编译,因为 NSInvalidArgumentException 被定义为字符串常量,它不是 NSException 类或继承自 NSException 的类。
    • 看来对openradar.me/8081169 的引用是准确的。我想这个异常将由 NSException 处理,但它目前有问题。
    猜你喜欢
    • 2012-08-05
    • 2011-08-10
    • 2012-11-04
    • 2010-10-17
    • 1970-01-01
    • 2012-06-27
    • 1970-01-01
    • 2011-06-05
    相关资源
    最近更新 更多