所以,我有一个想法捕获 主中的意外例外,并尝试清理并优雅地退出:
int main(int argc, char *argv[])
{
@autoreleasepool
{
//return UIApplicationMain(argc, argv, nil, NSStringFromClass([GRWAppDelegate class]));
@try
{
int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([GRWAppDelegate class]));
return retVal;
}
@catch (NSException *exception)
{
[Utilities setPreferencesDefaults];
}
}
}
这会捕获异常并更新首选项默认值。
然后我想,为什么退出,只是清理和重新启动,所以我把所有东西都包裹在一个while循环中:
int main(int argc, char *argv[])
{
while (YES)
{
@autoreleasepool
{
...
}
}
}
当然,如果真的有效,我就不会在这里。问题是,一旦再次执行
retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([GRWAppDelegate class]));
它会立即引发新的异常:
Assertion failure in void UIApplicationInstantiateSingleton(Class)(), /SourceCache/UIKit/UIKit-2380.17/UIApplication.m:2037
NSInternalInconsistencyException
@"There can only be one UIApplication instance."
有道理,那么有没有办法可以丢弃现有的单身人士并用新的替换它? (虽然我觉得如果可以的话,它并不是真正的单身人士)
目的是,我不希望应用程序崩溃,从而导致糟糕的用户体验。即使他们的状态没有完全恢复,我认为这仍然会比意外退出更好。
我可以尝试处理可能的预期异常,但这是为了尝试捕捉我无法预见的事情。
这应该只能抓住非常特殊的情况,所以如果不能做到这一点并不是那么大,但我想知道如何最好地应对这种情况。
答案 0 :(得分:6)
这不起作用,因为异常机制在跨堆栈帧抛出时不能正确清理。由于您在main中捕获异常,因此异常已越过多个堆栈帧。
Apple明确指出,仅的异常可用于不可恢复的编程错误。
请参阅bbum的回答:
“任何通过系统框架代码的异常都会使所述框架处于未定义状态。捕获所述异常并尝试从中恢复将导致内存泄漏,未定义的行为和崩溃。”
bbum Also。
来自Apple docs:
重要提示:您应该保留使用异常进行编程或意外的运行时错误,例如越界收集访问,尝试改变不可变对象,发送无效消息以及丢失与窗口服务器的连接。在创建应用程序时而不是在运行时,通常会使用异常处理这些类型的错误。
答案 1 :(得分:-1)
您可以创建顶级异常处理程序,并在应用程序首次启动时将其设置为默认异常处理程序。最好的地方是AppDelegate的applicationDidFinishLaunching:方法。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSSetUncaughtExceptionHandler(&exceptionHandler);
// some UI configuration here..
return YES;
}
void exceptionHandler(NSException *exception)
{
[Utilities setPreferencesDefaults];
// You can also write exception message into a log file as well.
NSLog(@"Stack trace: %@", [exception callStackReturnAddresses]);
}