objective-c 你如何实现全局 iPhone 异常处理?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1282364/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you implement global iPhone Exception Handling?
提问by Coocoo4Cocoa
I have one crash in my iPhone application that does throw an NSException. The crash reports are completely ambiguous in where the error is and what exactly is causing it. Is there a smart way for me to set a top level exception handler somewhere to see what is causing it? I can't replicate the problem myself, but a few of my beta users certainly can.
我的 iPhone 应用程序中有一次崩溃,确实抛出了 NSException。崩溃报告对于错误在哪里以及究竟是什么原因完全不明确。有没有一种聪明的方法可以让我在某处设置顶级异常处理程序以查看导致它的原因?我自己无法复制这个问题,但我的一些测试版用户当然可以。
What's a smart way to handle a problem of this nature?
处理这种性质的问题的聪明方法是什么?
回答by Paul McCabe
It seems like you are asking two questions here: how to set a top level exception handler; and how to deal with the issue of determining what the root cause is.
您似乎在这里问了两个问题:如何设置顶级异常处理程序;以及如何处理确定根本原因是什么的问题。
Catching the exception can be done in a few different ways, but for this the best approach would appear to be to set an exception handler using NSSetUncaughtExceptionHandler.
可以通过几种不同的方式捕获异常,但对于这种情况,最好的方法似乎是使用 NSSetUncaughtExceptionHandler 设置异常处理程序。
When an exception is raised in your app, it is handled by a default exception handler. This handler does nothing more than log a message to the console before the app closes. You can over-ride this by setting you own custom exception handler using the function stated above. The best place to do this would be in the app delegate applicationDidFinishLaunching: method.
当您的应用程序中引发异常时,它由默认异常处理程序处理。此处理程序仅在应用程序关闭之前将消息记录到控制台。您可以通过使用上述函数设置您自己的自定义异常处理程序来覆盖它。执行此操作的最佳位置是在应用程序委托 applicationDidFinishLaunching: 方法中。
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
NSSetUncaughtExceptionHandler(&myExceptionHandler);
}
Once you've set a custom handler, you'll want to expand on the default output in helping you determine what the cause is.
设置自定义处理程序后,您将需要扩展默认输出以帮助您确定原因。
void myExceptionHandler(NSException *exception)
{
NSArray *stack = [exception callStackReturnAddresses];
NSLog(@"Stack trace: %@", stack);
}
Unfortunately compared to OSX the iPhone appears quite limited in respect to producing a nice stack trace. The code above will produce some seemingly junk output; however, you can run this output through the atos tool, and you should be able to generate a useful stack trace from it.
不幸的是,与 OSX 相比,iPhone 在生成良好的堆栈跟踪方面显得非常有限。上面的代码会产生一些看似垃圾的输出;但是,您可以通过 atos 工具运行此输出,并且您应该能够从中生成有用的堆栈跟踪。
Another option is to follow the instructions on this articlewhich will help to produce a nice stack trace automatically.
另一种选择是按照本文中的说明进行操作,这将有助于自动生成良好的堆栈跟踪。
As this is going out to beta testers you may have to tinker about to get it working for you.
由于这是面向 Beta 测试人员的,您可能需要修补一下才能让它为您工作。
You say that you've not been able to replicate the problem yourself, only your users. In this case you may find this technical note from Apple useful:
您说您自己无法复制问题,只能复制您的用户。在这种情况下,您可能会发现 Apple 的这篇技术说明很有用:
https://developer.apple.com/library/content/technotes/tn2151/_index.html
https://developer.apple.com/library/content/technotes/tn2151/_index.html
UPDATE: While this post still contains useful info, some of the links it contains are dead irreversibly. It is advised to use the info from thisalternative post.
更新:虽然这篇文章仍然包含有用的信息,但它包含的一些链接已不可逆转地失效。建议使用此替代帖子中的信息。
回答by Durai Amuthan.H
If you are planning to do it on your own you could use one of these approaches
如果你打算自己做,你可以使用这些方法之一
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:
方法3:
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
}
Note:
笔记:
In my perspective don't try to send the exception details to server at the time of crashing send it when he starts the app again.
If you are going to use NSUserDefaults to save exception details then you have to synchronise it at the time of crashing otherwise it won't persist.
在我看来,当他再次启动应用程序时,不要尝试在崩溃时将异常详细信息发送到服务器。
如果你打算使用 NSUserDefaults 来保存异常细节,那么你必须在崩溃时同步它,否则它不会持续存在。
The following code snippet does the job.
下面的代码片段完成了这项工作。
- (void)applicationWillTerminate:(UIApplication *)application
{
[[NSUserDefaults standardUserDefaults]synchronize];
}
- If you prefer to save it on sqlite db then it persists itself no need to call anything to persist at the time of crashing
- 如果您更喜欢将它保存在 sqlite db 上,那么它会持续存在,在崩溃时不需要调用任何东西来持续存在
回答by Kendall Helmstetter Gelner
In XCode, you should always set a global breakpoint for objc_exception_throw. Then you (usually) get a far more meaningful stack trace as to what is actually trying to throw an exception.
在 XCode 中,您应该始终为objc_exception_throw. 然后,您(通常)会获得更有意义的堆栈跟踪,以了解实际尝试抛出异常的内容。
You can still get exceptions that originate in timer code or other places without your own code anywhere in the trace, but if you look at the method chain you can usually figure out generally what the exception is about (like having a notification sent where the target is gone).
您仍然可以在跟踪中的任何位置获得源自计时器代码或其他地方而没有您自己的代码的异常,但是如果您查看方法链,您通常可以大致弄清楚异常是关于什么的(例如在目标位置发送通知)离开了)。
回答by Matthew Frederick
Another option for tracking crash reports is Plausible CrashReporter, open source code to automatically send you crash reports from the field.
跟踪崩溃报告的另一个选项是Plausible CrashReporter,它是一种开源代码,可自动从现场向您发送崩溃报告。
There's also the CrashReporterDemo, another open source option that is a combination of Plausible CrashReporter and some server code to better track crash reports.
还有CrashReporterDemo,这是另一个开源选项,它结合了 Plausible CrashReporter 和一些服务器代码,可以更好地跟踪崩溃报告。
And lastly, there's MacDevCrashReporter, a service that appears to have similarities to iOSExceptional.com, suggested in another answer. I have no idea what their terms of service are, as I've not signed up for the beta. Definitely worth checking before getting in too deeply.
最后,还有MacDevCrashReporter,该服务似乎与 iOSExceptional.com 有相似之处,在另一个答案中提出。我不知道他们的服务条款是什么,因为我还没有注册测试版。在进入太深之前绝对值得检查。
回答by Mark
Check out Crittercism. It goes above and beyond what you're asking of here in that it lets you get this information for all users using your app, so you should be able to see your own crash.
查看Crittercism。它超越了您在这里的要求,因为它可以让您为所有使用您的应用程序的用户获取此信息,因此您应该能够看到自己的崩溃。
You can also upload the DYSM for your particular build and it will automatically symbolicate the crash for you on their website. That should provide you with the clearest stack-trace without being hooked up to the debugger.
您还可以为您的特定构建上传 DYSM,它会自动在他们的网站上为您表示崩溃。这应该为您提供最清晰的堆栈跟踪,而无需连接到调试器。
You might also want to make sure you are set to break on Objetive-C exceptions. In Xcode 4, in the breakpoints tab, you can add a Breakpoint Exception that breaks on both/either C++ and Obj-C exceptions. Without this on, most stack traces for exceptions thrown are pretty unhelpful.
您可能还想确保已设置为中断 Objetive-C 异常。在 Xcode 4 中,在断点选项卡中,您可以添加一个断点异常,该异常会同时中断 C++ 和 Obj-C 异常。如果没有这个,大多数抛出异常的堆栈跟踪是非常无用的。
Good luck!
祝你好运!
回答by kperryua
Have you tried NSSetUncaughtExceptionHandler?

