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 に答える