2009-11-24 83 views
9

我想在頂級iPhone異常處理程序中顯示UIAlertView。該處理函數如下:在iPhone頂級異常處理程序中顯示警報

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中捕獲錯誤並在返回之前顯示警報,它確實有效。我認爲alert視圖永遠不會有機會在異常處理程序中顯示,因爲應用程序正在終止(相反,如果我只是從applicationDidFinishLaunching中解脫出來,就不會坐在這裏)。有沒有辦法做到這一點?

回答

8

我不知道究竟如何[alertView show]實現,但我想它做了一些更改視圖層次,然後將自身設置上顯示下一次通過運行循環警報(看up NSRunLoop)。

但是,由於應用程序即將退出,控件不會返回到運行循環,因此警報從不顯示。這就是爲什麼你看到屏幕變暗(警報級別的UIWindow立即被show添加),但警告不會出現(這將發生在運行循環中)。

如果在異常處理程序的末尾包含[[NSRunLoop currentRunLoop] run],則可能會顯示警報。

如果您希望在完成警報後退出應用程序,您可以通過在while循環中調用NSRunLoop的runUntilDate:來檢查標誌的值,以查看警報是否已被解除。如果有,簡單地退出處理程序功能,你很好走。這意味着您必須在設置該標誌的警報上設置委託對象。

如果你想讓你的應用程序繼續運行...在那裏我不太確定。您可以讓運行循環繼續運行異常處理程序,但可能會有不良/奇怪的副作用。所以你可能應該讓應用程序退出。此外,如果您確定可以從異常中恢復,則應該在某處找到它。

+0

「[[NSRunLoop currentRunLoop]運行]」 的伎倆。謝謝! – 2009-12-08 04:49:04

+0

謝謝,我已經根據您的回答向此主題發佈了另一個解決方案。 – 2010-09-04 11:22:00

+0

你真的需要向用戶顯示錯誤信息嗎?如果你能夠默默地處理這個例外情況,也許最好,也不用擔心解決這個問題。 – 2011-03-01 22:03:05

0

您應該驗證是否達到了代碼或者您是否有顯示問題。

NSLog的將澄清。

如果沒有達到,就需要防止應用程序停機,您可能需要延遲作用得到了這方面的警報呼叫:

[self performSelector: @selector(showAlert:) withObject:@"msg" afterDelay: 0.1]; 

如果你正在接近它,執行上下文不一個問題,但你根本沒有看到警報,然後[警報顯示]可能不是最高級別顯示。在這種情況下,你可能需要通過showinview重定向消息,例如與actionsheet:

topDelegate=[[UIApplication sharedApplication] delegate]; 
topDelegateWindow=[topDelegate.window.subviews objectAtIndex:0]; 

[actionSheet showInView:topDelegateWindow]; 
9

感謝benzado,這是我認爲是一個偉大的通用頂級異常處理程序。我是一個初學者,所以希望它做得很好,但它確實工作:)

在我的... appDelegate。L:

- (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); 
+1

看起來不錯。就我個人而言,我會創建一個單獨的對象作爲警報的委託。由於我們處於災難模式,因此與應用代碼的其餘部分隔離是有意義的。但否則,看起來不錯。 – benzado 2010-09-05 16:51:35

+0

如果與uialertview + blocks實現結合使用,這可以變得更加漂亮。像這樣(不是我的代碼): https://github.com/MugunthKumar/UIKitCategoryAdditions – 2012-10-21 12:27:42

相關問題