9

我正在尝试在顶级 iPhone 异常处理程序中显示 UIAlertView。处理函数如下所示:

void applicationExceptionHandler(NSException *ex) {
  UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error"
                                                      message:[ex reason]
                                                      delegate:nil
                                             cancelButtonTitle:@"OK"
                                             otherButtonTitles:nil];
  [alertView show];
}

我在其他地方看到过类似的代码(例如,NSSetUncaughtExceptionHandler not catch all errors on iPhone)。

如果我在调试器中单步执行,我可以看到调用了异常处理程序,并且我可以看到当前屏幕变暗,好像它要在它前面显示警报一样,但什么也没有出现。在调试器之外,应用程序会立即退出并返回系统主屏幕。

如果我在 applicationDidFinishLaunching 中捕获错误并在返回之前在那里显示警报,它确实有效。我假设警报视图永远不会有机会在异常处理程序中显示,因为应用程序正在终止(而不是坐在那里,如果我只是退出 applicationDidFinishLaunching)。有没有办法使这项工作?

4

3 回答 3

9

非常感谢 benzado,我认为这是一个很棒的通用顶级异常处理程序。我是初学者,所以希望它做得正确,但它确实有效:)

在我的 ...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);
于 2010-09-04T11:21:30.157 回答
8

我不知道具体是如何[alertView show]实现的,但我想它会对视图层次结构进行一些更改,然后将自身设置为在下一次通过运行循环时显示警报(查找NSRunLoop)。

但是,由于应用程序即将退出,控制不会返回到运行循环,因此永远不会显示警报。这就是为什么您看到屏幕变暗(警报级别的 UIWindow 立即添加show)但警报没有出现(这将在运行循环中发生)。

如果您[[NSRunLoop currentRunLoop] run]在异常处理程序的末尾包含,则可能会出现警报。

如果您想让您的应用程序在警报完成后退出,您可以通过runUntilDate:在 while 循环中调用 NSRunLoop 来实现,检查标志的值以查看警报是否已被解除。如果有,只需退出处理函数即可。这意味着您必须在设置该标志的警报上设置一个委托对象。

如果你想让你的应用程序继续运行......我不太确定。您可以让运行循环继续用完异常处理程序,但这可能会产生不良/奇怪的副作用。所以你可能应该让应用退出。此外,如果您确定可以从异常中恢复,那么您应该在某个地方捕获它。

于 2009-12-03T08:43:17.353 回答
0

您应该验证是否达到了代码,或者您是否只是有显示问题。

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];
于 2009-11-25T16:17:17.987 回答