2009-11-24 3 views
9

최상위 iPhone 예외 처리기에 UIAlertView를 표시하려고합니다. 핸들러의 기능은 다음과 같습니다 : 나는 (예를 들어, NSSetUncaughtExceptionHandler not catch all errors on iPhone) 다른 곳에서 비슷한 코드를 본 적이iPhone 최상위 예외 처리기에 경고를 표시합니다.

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

.

디버거에서 단일 단계로 진행하면 예외 처리기가 호출 된 것을 볼 수 있으며 현재 화면이 어두워 보이는 것을 볼 수 있습니다. 그러나 아무 것도 나타나지 않습니다. 디버거 외부에서는 앱이 즉시 종료되고 시스템 홈 화면으로 돌아갑니다.

나는 applicationDidFinishLaunching에서 오류를 잡아서 거기에 경고를 표시하면 작동합니다. 응용 프로그램이 종료되기 때문에 경고보기는 예외 처리기에서 표시 할 수있는 기회를 얻지 못한다고 가정합니다 (applicationDidFinishLaunching에서 손을 떼면 아무 것도하지 않는 대신). 이 일을 할 수있는 방법이 있습니까?

답변

8

내가 구현하는 방법을 [alertView show] 정확히 모르겠지만, 나는 그것이 뷰 계층을 일부 변경하게 상상하고 실행 루프를 통해 다음 패스에 경고를 표시하는 자체 설정 (볼 위로 NSRunLoop).

그러나 앱이 종료되기 때문에 제어가 실행 루프로 돌아 가지 않으므로 경고가 표시되지 않습니다. 그래서 화면이 어둡게 보입니다 (경고 수준 UIWindow는 즉시 show에 의해 추가됩니다). 경고는 나타나지 않습니다 (실행 루프에서 발생합니다).

예외 처리기 끝에 [[NSRunLoop currentRunLoop] run]을 포함하면 경고가 표시 될 수 있습니다.

경고가 완료되면 앱을 종료하려면 잠시 루프에서 NSRunLoop의 runUntilDate:을 호출하고 플래그 값을 확인하여 경고가 아직 해제되었는지 확인하십시오. 그렇다면 단순히 핸들러 함수를 종료하면됩니다. 즉, 해당 플래그를 설정하는 경고에 대리자 객체를 설정해야합니다.

앱을 계속 실행하려면 ... 확실하지 않습니다. 실행 루프가 예외 처리기를 계속 실행하게 할 수는 있지만 그/나 이상한 부작용이있을 수 있습니다. 그래서 앱을 종료시켜야합니다. 게다가 예외에서 복구 할 수 있다고 확신한다면 어딘가에 잡았어야합니다.

+0

"[[NSRunLoop currentRunLoop] 실행]"트릭을했다. 감사! –

+0

고마워, 나는 당신의 대답을 기반 으로이 스레드에 다른 해결책을 게시했습니다. –

+0

정말 사용자에게 오류 메시지를 표시해야합니까? 예외를 자동으로 처리 할 수 ​​있다면 어쨌든이 문제를 해결하는 것에 대해 걱정할 필요가없는 것이 가장 좋습니다. –

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

Benado에게 감사의 말을 전하며, 여기에는 훌륭한 일반적인 최상위 예외 처리기가 있다고 생각합니다. 나는 초보자 다. 그래서 그것은 올바르게하게된다. 그러나 그것은 일한다 :)

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

좋아 보인다. 개인적으로 경고 대상자 역할을 수행 할 별도의 개체를 만듭니다. 재난 모드에 있기 때문에 나머지 앱 코드와 분리되어있는 것이 좋습니다. 하지만 그렇지 않으면 좋아 보인다. – benzado

+0

uialertview + 블록 구현과 결합하면이 방법을 더 쉽게 만들 수 있습니다. 이 코드 (내 코드 아님) : https://github.com/MugunthKumar/UIKitCategoryAdditions –

관련 문제