【问题标题】:Catching NSException in main在 main 中捕获 NSException
【发布时间】:2014-06-30 07:56:03
【问题描述】:

我接管的 iOS 应用程序处理 NSExceptions 的方式与我之前看到的不同,我想知道为什么它现在不起作用。

在 main.m 文件中,老开发者有这个逻辑:

int main(int argc, char *argv[])
{
    @autoreleasepool {
        int retVal = 0;
        @try {
            retVal =  UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        }
        @catch (NSException *exception) {
            //
            //Logic to save Exception in DataStore
            //
            NSLog(@"Exception - %@",[exception description]);
            exit(EXIT_FAILURE);
        }
        return retVal;
    }
}

当应用再次启动时,您会收到将异常发送给我们的提示,如果您确认它会将异常发送到我们的服务器。

我最近为应用程序的 iOS 7 推送了一个更优化的更新,并注意到我不再从崩溃的应用程序中收到任何这些错误报告。

所以我通过以下我知道被调用的代码对其进行了测试:

NSArray *array = [NSArray new];

id object = [array objectAtIndex:4];

我收到这个:

2014-05-12 14:55:57.575 APPNAME[17989:60b] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 4 beyond bounds for empty array'
*** First throw call stack:
(0x18ab0b09c 0x196a89d78 0x18aa0c680 0x10007f498 0x18d9e02c0 0x18da997d0 0x18da996cc 0x18da98ba0
 0x18da98840 0x18da98564 0x18da984e4 0x18d9dad78 0x18d5d70cc 0x18d5d1c94 0x18d5d1b4c 
 0x18d5d13d4 0x18d5d1178 0x18d5caa30 0x18aacb7e0 0x18aac8a68 0x18aac8df4 0x18aa09b38 
 0x19042f830 0x18da480e8 0x100036b98 0x197073aa0)
libc++abi.dylib: terminating with uncaught exception of type NSException

如您所见,该异常并未被记录或保存,而是完全未被捕获。

2 个问题:

  1. 这是不好的做法吗?我不这么认为,但我是jr。开发人员并不确定是否有更好的方法可以在没有第三方服务的情况下执行此操作?

  2. 您是否知道 iOS 7 中会影响此(未触及)逻辑的任何更改?

【问题讨论】:

  • 我的猜测是 Apple 现在在 UIApplicationMainUIApplication 类中的某处有一个异常处理程序

标签: ios objective-c nsexception


【解决方案1】:

根据Exception Programming Topics,您可以使用 NSSetUncaughtExceptionHandler 函数来处理未捕获的异常。试试下面的代码:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSSetUncaughtExceptionHandler(handleUncaughtException);
    @throw [NSException exceptionWithName:NSGenericException
                                   reason:@"Test uncaught exception handling"
                                 userInfo:nil];

    return YES;
}

void handleUncaughtException(NSException *exception)
{
    NSLog(@"Exception - %@",[exception description]);
    exit(EXIT_FAILURE);
}

【讨论】:

  • 我将此标记为正确答案,因为在我提出这个问题后,我找到了这个确切的答案并且它有效。但我有一个问题,这是否是好的做法?
  • 我认为这是一种很好的做法,但我想我们应该请@bbum 解释为什么他建议不要使用它
【解决方案2】:

这是不好的做法吗?我不这么认为,但我是jr。开发商和 不太确定,是否有更好的方法来做到这一点而没有第三 派对服务?

是的,这是不好的做法。 UIApplicationMain() 是一个黑洞;一旦将控制权传递给该函数,就不可能再次调用main() 中该调用之外的任何代码。

这也是一个幼稚的实现;它向标准输出记录的信息少于正常的异常处理机制(这是您看到的输出)。它隐藏了对调试有用的信息,并且可能会绕过标准的崩溃报告机制。

请注意,还有一个全局未处理的异常处理钩子。我不建议使用它,但它确实存在。

您是否知道 iOS 7 中会影响到这一点的任何更改(未触及) 逻辑?

不是手头的,但我没看过。不过,UIApplicationMain() 又是一个黑洞。它通常不会返回。

【讨论】:

  • 感谢您的回答。我看到这是一种不好的做法,因为它依赖于 uIApplicationMain。日志因素不是问题,因为我们的异常处理 dao 和报告类保存了大量数据,并且还包括我们发送的面包屑。似乎 iOS 7 可能已经改变了它的返回方式,因为在 iOS7 之前它们都被报告了。
猜你喜欢
  • 2015-12-21
  • 2016-11-06
  • 2015-11-17
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 2011-02-12
  • 2016-09-24
相关资源
最近更新 更多