在iPhone顶级异常处理程序中显示警报
我试图在顶级iPhone异常处理程序中显示UIAlertView。处理程序函数如下所示:在iPhone顶级异常处理程序中显示警报,iphone,objective-c,exception,uialertview,Iphone,Objective C,Exception,Uialertview,我试图在顶级iPhone异常处理程序中显示UIAlertView。处理程序函数如下所示: void applicationExceptionHandler(NSException *ex) { UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error" message:[ex reason]
void applicationExceptionHandler(NSException *ex) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error"
message:[ex reason]
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alertView show];
}
我在其他地方见过类似的代码(例如)
如果我在调试器中单步执行,我可以看到调用了异常处理程序,并且我可以看到当前屏幕变暗,好像它将在它前面显示警报,但什么也没有出现。在调试器之外,应用程序立即退出并返回系统主屏幕
如果我在ApplicationIDFinishLaunching中捕获错误并在返回之前在那里显示警报,它确实可以工作。我假设警报视图永远不会有机会显示在异常处理程序中,因为应用程序正在终止(而不是坐在那里无所事事,如果我只是退出ApplicationIDFinishLaunching)。有什么方法可以使这项工作正常吗?您应该验证是否达到了代码要求,或者是否只是显示问题 NSLog将澄清这一点 如果未联系到,您需要防止应用程序关闭,并且您可能需要延迟操作以脱离警报呼叫的上下文:
[self performSelector: @selector(showAlert:) withObject:@"msg" afterDelay: 0.1];
如果您正在访问它,并且执行上下文不是问题,但您只是没有看到警报,那么[alert show]可能不是显示的顶级。在这种情况下,您可能需要通过showinview重定向消息,例如使用操作表:
topDelegate=[[UIApplication sharedApplication] delegate];
topDelegateWindow=[topDelegate.window.subviews objectAtIndex:0];
[actionSheet showInView:topDelegateWindow];
我不清楚
[alertView show]
是如何实现的,但我想它会对视图层次结构进行一些更改,然后将自身设置为在下一次运行循环时显示警报(查找nsrunlop
)
但是,由于应用程序即将退出,控件不会返回到运行循环,因此警报永远不会显示。这就是为什么您会看到屏幕变暗(警报级别窗口由show
立即添加),但警报不会出现(这将发生在运行循环中)
如果在异常处理程序的末尾包含[[nsrunlop currentlunloop]run]
,则可能会出现警报
如果要让应用程序在警报完成后退出,可以在while循环中调用nsrunlop的runUntilDate:
,检查标志值以查看警报是否已解除。如果有,只需退出handler函数即可。这意味着您必须在设置该标志的警报上设置一个委托对象
如果你想让你的应用程序继续运行。。。我不太确定。您可以让运行循环继续在异常处理程序中运行,但这可能会产生不良/奇怪的副作用。所以你可能应该让应用退出。此外,如果您确信可以从异常中恢复,那么您应该在某个地方捕获到它。感谢benzado的帮助,下面是我认为非常棒的通用顶级异常处理程序。我是一个初学者,所以希望它能正确完成,但它确实有效:) 在my…appDelegate.m中:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[window makeKeyAndVisible];
NSSetUncaughtExceptionHandler(&exceptionHandler);
return YES;
}
BOOL exceptionAlertDismissed = FALSE;
void exceptionHandler(NSException *exception)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"App Committed Suicide"
message:@"Oh dear, that wasn't supposed to happen. You will have to restart the application... sorry!"
delegate:[[UIApplication sharedApplication] delegate] cancelButtonTitle:nil otherButtonTitles:@"That's ok!", @"Erm, bye...", nil];
[alert show];
[alert release];
while (exceptionAlertDismissed == FALSE)
{
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
exceptionAlertDismissed = TRUE;
}
在我的…appDelegate.h中:
@interface ...appDelegate : NSObject <UIApplicationDelegate, UIAlertViewDelegate>
...
void exceptionHandler(NSException *exception);
@interface…appDelegate:NSObject
...
无效异常处理程序(NSException*exception);
谢谢,我根据您的回答发布了另一个解决方案。您真的需要向用户显示错误消息吗?如果您能够以静默方式处理异常,并且不必担心如何解决此问题,也许这将是最好的选择。@Nick理想情况下是的,但这是处理未捕获、不可预见、意外异常的代码。希望它永远不会被调用,但如果是,另一种选择是让应用程序在没有警告的情况下突然退出。看起来不错。就我个人而言,我会创建一个单独的对象作为警报的委托。由于我们处于灾难模式,因此与应用程序的其他代码隔离是有意义的。如果与uialertview+blocks实现相结合,则可以很容易地使其变得更漂亮。像这样(不是我的代码):