0

以下を使用して、次の例外ハンドラーを実装しました。

NSSetUncaughtExceptionHandler(&ExceptionHandler)

次に、ハンドラーは以下を使用して handleException を呼び出します。

[[AppContext alloc] init] performSelectorOnMainThread:@selector(handleException:) withObject:exception waitUntilDone:YES];

そのように実装されています:

NSString *message = [NSString stringWithFormat:MSG_UNHANDLED_EXCEPTION_FORMAT, exception.reason, [exception callStackSymbols]];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:TITLE_UNHANDLED_EXCEPTION message:message delegate:self cancelButtonTitle:nil otherButtonTitles:nil];

[alert show];

CFRunLoopRef runLoop = CFRunLoopGetCurrent();
CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);

while (!_quit) {
    for (NSString *mode in (__bridge NSArray *)allModes) {
        CFRunLoopRunInMode((__bridge CFStringRef)mode, 0.001, false);
    }
}

CFRelease(allModes);

これは、次のシナリオを除いてうまく機能します。UIAlertView は引き続き表示されますが、ユーザー インタラクションは使用できなくなります (ユーザーはメッセージをスクロールしたり、[OK] をタップしたりできません)。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(){

    // do long work on another thread...

    dispatch_async(dispatch_get_main_queue(), ^(){

        // updating the UI so get back on main thread...
        // exception occurs in this block (example)...
        @throw [NSException exceptionWithName:@"DispatchAsyncToMainThreadException" reason:@"Example" userInfo:nil];

    });

注: 私は実稼働コードで実際に例外をスローしているわけではありません。これは純粋に、未処理の例外が生成されている場所を示すためのものです。

メイン キューにディスパッチされたブロック内から例外が発生しているときに、説明する必要があるのは何ですか。

4

1 に答える 1

1

のドキュメントにNSSetUncaughtExceptionHandlerは、アプリケーションが終了する前に最後のエラー ログを記録する必要があると記載されています。この時点で UI が動作することは期待できません。エラーの詳細をファイル システムのどこかに記録しているだけです。ユーザーがアプリケーションを再度開いたときに、問題が発生したことをユーザーに知らせ、回復/レポート オプションを提供することができます。

説明
プログラムが終了する前に最後のログを実行できるトップレベルのエラー処理関数を設定します。

于 2013-08-22T20:25:27.187 に答える