2

当出现严重错误以至于我的应用程序无法继续并需要退出时,我想向用户弹出一个警告框,然后在他们点击 OK 按钮时关闭应用程序。听起来很简单,对吧?

但问题是:我的致命错误处理程序被第 3 方库调用(我没有他们的源代码)。我在初始化时给他们一个指向我的致命错误处理程序的指针,当他们遇到致命错误时,他们只需调用该例程并期望它永远不会返回。如果它返回,第 3 方库将假定我已经处理了错误,并且它将继续运行(可能会损坏数据,因为现在处于不一致的状态)。我可以在我的错误处理程序结束时退出应用程序(这是他们所期望的),但我希望能够首先向用户显示一条消息,告诉他们问题出在哪里。

不幸的是,如果我这样做:

-(void)fatalErrorHandler:(NSString *)msg
{
    // Log the error and shut down all the things that need
    // to be shut down before we exit
    // ...

    // Show an alert to the user to tell them what went wrong
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:msg delegate:self cancelButtonTitle:@"Close" otherButtonTitles:nil];
    [alert show];
}


-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    exit(-1);
}

fatalErrorHandler 在 [alert show] 之后立即返回,它告诉第 3 方库我已经处理了错误,并且它将继续运行,就好像什么都没发生一样。这不好。

我不需要从 fatalErrorHandler 返回。曾经。但由于我在主线程上,所以 UIAlertView 在 fatalErrorHandler 返回之前不会出现。一个第 22 个问题。

关于如何在不从致命错误处理程序返回的情况下向用户显示警报的任何想法?

4

3 回答 3

0

根据您所写的“fatalErrorHandler 在 [alert show] 之后立即返回,它告诉 3rd 方库我已经处理了错误,它将继续,就好像什么都没发生一样。”

我猜你真正需要的是在调用 fatalErrorHandler 方法时暂停一切。为此,您可以在显示 alertView 之前停止所有 NSTimer、排队方法等。

或者,您可以通过不同的线程显示 alertView,然后使用 usleep(long long time) 暂停 fatalErrorHandler 所在的线程。

于 2013-08-08T21:18:05.637 回答
0

好的,wesley6j 的回答给了我一个想法。这是我想出的:

-(void)fatalErrorHandler:(NSString *)msg
{
    // Pop up an alert to tell the user what went wrong.  Since this error
    // handler could be called from any thread, we have to make sure this happens
    // on the main thread because it does UI stuff
    [self performSelectorOnMainThread:@selector(showMessage:) withObject:msg waitUntilDone:YES];

    // Now, if we're NOT on the main thread, we can just sleep forever and never
    // return from here.  The error handler will exit the app after the user 
    // dismisses the alert box.
    if (![NSThread isMainThread])
        Sleep(0x7fffffff);
    else
    {
        // OTOH, if we ARE on the main thread, we have to get a bit creative.
        // We don't ever want to return from here, because this is a fatal error
        // handler and returning means the caller can continue on its way as if
        // we "handled" the error, which we didn't.  But since we're on the main
        // thread, we can't sleep or exit because then the user will never see 
        // the alert box we popped up in showMessage.  So we loop forever and 
        // keep calling the main run loop directly to let it do its processing
        // and show the alert.  This is what the main run loop does anyway, so
        // in effect, we just become the main run loop.
        for (;;)
        {
            [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate date]];
        }
    }
}


-(void)showMessage:(NSString *)msg
{            
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:msg delegate:self cancelButtonTitle:@"Close" otherButtonTitles:nil];
    [alert show];
    [alert release];
}

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    exit(-1);
}

这完美地工作并且完全符合我的需要。

于 2013-08-09T12:09:21.433 回答
0

我不知道这是否可行,但是如果在它的主体中启动一个while循环,sleep比如说,每个循环 1 秒呢?当Bool变量被设置为时,while 将退出YES,也许从alertViewDelegate.

于 2013-08-08T21:11:05.243 回答