你如何实现全球iPhoneexception处理?

我有一个崩溃在我的iPhone应用程序,抛出一个NSException。 崩溃报告是完全不明确的错误在哪里,究竟是什么导致它。 有没有一个聪明的方法来设置一个顶级exception处理程序,以查看是什么造成的? 我不能自己复制这个问题,但是我的一些testing版用户当然可以。

处理这种性质问题的一个聪明的办法是什么?

好像你在这里问两个问题:如何设置一个顶级exception处理程序; 以及如何处理确定根本原因的问题。

捕获exception可以通过几种不同的方式完成,但是最好的办法是使用NSSetUncaughtExceptionHandler来设置exception处理程序。

当您的应用程序中引发exception时,将由默认的exception处理程序处理。 该处理程序只会在应用程序closures之前将消息logging到控制台。 您可以通过使用上述函数设置您自己的自定义exception处理程序来覆盖此内容。 执行此操作的最佳位置应该在应用程序委托applicationDidFinishLaunching:方法中。

- (void)applicationDidFinishLaunching:(UIApplication *)application { NSSetUncaughtExceptionHandler(&myExceptionHandler); } 

一旦你设置了自定义处理程序,你就需要扩展默认输出来帮助你确定原因。

 void myExceptionHandler(NSException *exception) { NSArray *stack = [exception callStackReturnAddresses]; NSLog(@"Stack trace: %@", stack); } 

不幸的是,与OSX相比,iPhone在生成一个漂亮的堆栈跟踪方面似乎相当有限。 上面的代码会产生一些看似垃圾的输出; 不过,你可以通过atos工具运行这个输出,你应该能够从中产生一个有用的堆栈跟踪。

另一个select是遵循本文的说明, 这将有助于自动生成一个不错的堆栈跟踪。

由于这是betatesting人员,你可能需要鼓捣它为你工作。

你说你不能自己复制这个问题,只有你的用户。 在这种情况下,您可能会发现苹果的技术说明很有用:

https://developer.apple.com/library/content/technotes/tn2151/_index.html

更新 :虽然这篇文章仍然包含有用的信息,它包含的一些链接是不可逆转的死亡。 build议使用这个替代post中的信息。

如果你打算自己做,你可以使用这些方法之一

Approach1:

 void onUncaughtException(NSException* exception) { //save exception details } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSSetUncaughtExceptionHandler(&onUncaughtException); //Add coding to find if any exception has occurred from saved details if so send it to server or ask user to comment on the issue. //Rest of the coding } 

Approach2:

 void onUncaughtException(NSException* exception) { //Save exception details } int main(int argc, char *argv[]) { @autoreleasepool { NSSetUncaughtExceptionHandler(&onUncaughtException); return UIApplicationMain(argc, argv, nil, NSStringFromClass([SGGI_AppDelegate class])); } } -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //Add coding to find if any exception has occurred from saved details if so send it to server or ask user to comment on the issue. //Rest of the coding } 

Approcach3:

 int main(int argc, char *argv[]) { @autoreleasepool { @try { return UIApplicationMain(argc, argv, nil, NSStringFromClass([SGGI_AppDelegate class])); } @catch (NSException *exception) { //Save the exception } @finally { } } } -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //Add coding to find if any exception has occurred from saved details if so send it to server or ask user to comment on the issue. //Rest of the coding } 

注意:

  • 在我看来,不要试图在发生崩溃时向服务器发送exception详细信息,当他再次启动应用程序时发送它。

  • 如果你打算使用NSUserDefaults来保存exception细节,那么你必须在崩溃时同步它,否则它将不会持续。

以下代码片段完成这项工作。

  - (void)applicationWillTerminate:(UIApplication *)application { [[NSUserDefaults standardUserDefaults]synchronize]; } 
  • 如果你喜欢把它保存在sqlite数据库然后它坚持自己没有必要调用任何东西在崩溃时坚持

在XCode中,您应该始终为objc_exception_throw设置一个全局断点。 然后,你(通常)得到一个更有意义的堆栈跟踪,实际上是在试图抛出一个exception。

你仍然可以得到在定时器代码或其他地方没有你自己的代码在跟踪任何地方的代码的exception,但是如果你看看方法链,你通常可以弄清楚什么是例外情况(比如有一个通知发送目标离开了)。

此外, BugSense.com可用于iOS项目

你有没有试过NSSetUncaughtExceptionHandler

跟踪崩溃报告的另一个select是Plausible CrashReporter ,这是一个开源代码,可以自动从现场向您发送崩溃报告。

还有CrashReporterDemo ,另一个开源的选项,它是一个Plausible CrashReporter和一些服务器代码的组合,以更好地跟踪崩溃报告。

最后,还有MacDevCrashReporter ,这个服务似乎与iOSExceptional.com有相似之处,在另一个答案中提出。 我不知道他们的服务条款是什么,因为我还没有注册testing。 在深入之前绝对值得检查。

检查出Crittercism 。 它超越了你在这里所要求的,它可以让你获得所有使用你的应用程序的用户的信息,所以你应该能够看到你自己的崩溃。

您也可以上传您的特定版本的DYSM,它会自动在您的网站上标志着您的崩溃。 这应该为您提供最清晰的堆栈跟踪,而不必连接到debugging器。

你也可能想要确定你打破了Objetive-Cexception。 在Xcode 4中的breakpoints选项卡中,可以添加一个断点exception,该断点exception既可以在C ++也可以在Obj-Cexception中断裂。 如果没有这个,大多数的堆栈跟踪抛出的exception是相当无益的。

祝你好运!