我在我的iPhone应用程序中遇到了一个崩溃问题,它会抛出一个NSException异常。崩溃报告中并没有明确指出错误出现的位置和具体引起崩溃的原因。有没有什么聪明的方法让我设置一个顶层异常处理程序来查看是什么导致了这个问题?我自己无法复制这个问题,但我的几个测试用户却可以。
如何聪明地处理这种情况的问题?
我在我的iPhone应用程序中遇到了一个崩溃问题,它会抛出一个NSException异常。崩溃报告中并没有明确指出错误出现的位置和具体引起崩溃的原因。有没有什么聪明的方法让我设置一个顶层异常处理程序来查看是什么导致了这个问题?我自己无法复制这个问题,但我的几个测试用户却可以。
如何聪明地处理这种情况的问题?
看起来你在这里问了两个问题:如何设置顶层异常处理程序;以及如何解决确定根本原因的问题。
捕获异常可以用几种不同的方式,但对于此问题,最好的方法似乎是使用 NSSetUncaughtExceptionHandler 设置异常处理程序。
当应用程序中出现异常时,它将由默认异常处理程序处理。该处理程序仅在应用程序关闭之前向控制台记录一条消息。您可以通过使用上述函数设置自定义异常处理程序来覆盖此行为。最好的位置是在应用委托 applicationDidFinishLaunching: 方法中进行设置。
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
NSSetUncaughtExceptionHandler(&myExceptionHandler);
}
一旦你设置了自定义处理程序,你就希望在帮助你确定原因方面扩展默认输出。
void myExceptionHandler(NSException *exception)
{
NSArray *stack = [exception callStackReturnAddresses];
NSLog(@"Stack trace: %@", stack);
}
不幸的是,与OSX相比,iPhone在生成漂亮的堆栈跟踪方面似乎非常有限。上面的代码会产生一些看似垃圾的输出;但是,您可以通过atos工具运行此输出,并应该能够从中生成有用的堆栈跟踪。
另一个选项是按照这篇文章的说明自动产生漂亮的堆栈跟踪。
由于这将发送给beta测试人员,您可能需要调整一下才能使其对您起作用。
您说您自己无法复制该问题,只有您的用户发生了问题。在这种情况下,您可能会发现苹果公司的这篇技术说明有用:
更新:虽然这篇文章仍包含有用的信息,但其中一些链接已经永久失效。建议使用这篇替代文章中的信息。
如果您打算自己完成,可以使用以下其中一种方法之一
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
}
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
}
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
}
在我看来,在崩溃时不要尝试将异常详细信息发送到服务器,而是在他再次启动应用程序时发送。
如果你要使用NSUserDefaults保存异常信息,则必须在崩溃时同步它,否则它不会持久化。
以下代码片段可以完成这项工作。
- (void)applicationWillTerminate:(UIApplication *)application
{
[[NSUserDefaults standardUserDefaults]synchronize];
}
[[NSUserDefaults standardUserDefaults]synchronize]
)它。 - Durai Amuthan.Hobjc_exception_throw
设置全局断点。然后,通常可以获得更有意义的堆栈跟踪,以确定实际上是谁试图引发异常。跟踪崩溃报告的另一个选择是开源代码Plausible CrashReporter,它可以自动向您发送来自现场的崩溃报告。
还有另一个开源选项CrashReporterDemo,它是Plausible CrashReporter和一些服务器代码的组合,可以更好地跟踪崩溃报告。
最后,还有MacDevCrashReporter,这个服务似乎与iOSExceptional.com有相似之处,在另一个答案中建议使用。我不知道他们的服务条款是什么,因为我没有注册beta版。在深入了解之前一定要检查。
你尝试过使用 NSSetUncaughtExceptionHandler
吗?