代码之家  ›  专栏  ›  技术社区  ›  John Gallagher

如何阻止HIToolbox捕获我的异常?

  •  4
  • John Gallagher  · 技术社区  · 14 年前

    why my app isn't being brought down by exceptions .

    问题

    当通过操作在主线程上引发异常时,应用程序仍然不会崩溃。

    根据 Dave's answer to my original question ,我在NSApplication上实现了reportException类别,并设置了未捕获的异常处理程序。

    代码

    -(IBAction)crashOnMainThread:(id)sender {
        [self performSelectorOnMainThread:@selector(crash) withObject:nil waitUntilDone:YES];
    }
    
    -(void)crash {
        // To test out the exception handling
        [NSException raise:NSInternalInconsistencyException format:@"This should crash the app."];
    }
    

    当我按下按钮,我的应用程序不会崩溃。当我查看控制台日志时,我看到:

    06/09/2010 14:12:25 EHTest1[26384]  HIToolbox: ignoring exception 'This should crash the app.' that raised inside Carbon event dispatch
    (
        0   CoreFoundation                      0x00007fff80ab4cc4 __exceptionPreprocess + 180
        1   libobjc.A.dylib                     0x00007fff819560f3 objc_exception_throw + 45
        2   CoreFoundation                      0x00007fff80ab4ae7 +[NSException raise:format:arguments:] + 103
        3   CoreFoundation                      0x00007fff80ab4a74 +[NSException raise:format:] + 148
        4   EHTest1                             0x00000001000010e3 -[EHTest1_AppDelegate crashLapsus] + 63
        5   Foundation                          0x00007fff88957c25 -[NSObject(NSThreadPerformAdditions) performSelector:onThread:withObject:waitUntilDone:modes:] + 234
        6   Foundation                          0x00007fff8896ad48 -[NSObject(NSThreadPerformAdditions) performSelectorOnMainThread:withObject:waitUntilDone:] + 143
        7   EHTest1                             0x0000000100001030 -[EHTest1_AppDelegate crashOnMainThread:] + 60
        8   AppKit                              0x00007fff85c7e152 -[NSApplication sendAction:to:from:] + 95
        9   AppKit                              0x00007fff85ca26be -[NSMenuItem _corePerformAction] + 365
    
        ** Snip **
    

    看起来碳元素是个例外,这真的很烦人。

    这表明,对于任何操作代码,都需要立即在后台线程中运行它,以便将所有异常注册为未捕获。呵呵?我没见过这样的代码。

    我试过的

    延迟崩溃应用程序,使其无法连接到UI元素。很好。

    -(BOOL)exceptionHandler:(NSExceptionHandler *)sender 
      shouldHandleException:(NSException *)exception 
                       mask:(unsigned int)aMask {
          abort();
          return YES;
    }
    
    -(void)applicationWillFinishLaunching:(NSNotification *)aNotification {
          NSExceptionHandler *handler = [NSExceptionHandler defaultExceptionHandler];
          [handler setExceptionHandlingMask:NSLogAndHandleEveryExceptionMask];
          [handler setDelegate:self];
    }
    

    这里的问题是,无论捕获与否,每个异常都会崩溃。

    问题

    • 我怎样才能停止HIToolbox捕捉异常,使我的应用程序使用未捕获的异常处理程序并崩溃?
    • 如果不行,还有什么办法?

    这使我非常恼火,所以任何帮助都将不胜感激。

    2 回复  |  直到 7 年前
        1
  •  6
  •   catlan    5 年前

    我回答了您关于这个主题的最后一个问题,并遇到了与Carbon的HIToolbox捕获IBActions抛出的异常相同的问题。

    previous answer NSSetUncaughtExceptionHandler() 生活(我相信)在链条的顶端。

    1. 添加 异常处理.framework 到Xcode项目
    2. #import "ExceptionHandlerDelegate.h"

    AppDelegate.m公司 :

    // Very first message sent to class
    + (void)initialize
    {
        NSExceptionHandler *exceptionHandler = [NSExceptionHandler defaultExceptionHandler];
        unsigned int handlingMask = NSLogAndHandleEveryExceptionMask;
        [exceptionHandler setExceptionHandlingMask:handlingMask];
        [exceptionHandler setDelegate:self];
    
        // ...
    }
    
    
    #pragma mark -
    #pragma mark NSExceptionHandler Delegate Methods
    
    // Called 1st: Should NSExceptionHandler log the exception?
    - (BOOL)exceptionHandler:(NSExceptionHandler *)sender shouldLogException:(NSException *)exception mask:(unsigned int)aMask
    {
        // ...log NSException if desired...
    
        return NO;  // Changes to YES if NSExceptionHandler should handle logging
    }
    
    // Called 2nd: Should NSExceptionHandler handle the exception?
    - (BOOL)exceptionHandler:(NSExceptionHandler *)sender shouldHandleException:(NSException *)exception mask:(unsigned int)aMask
    {
        // ...crash your app here (e.g. [NSApp terminate:self]; )
    
        // ...or handle the NSException and return YES/NO accordingly
    
        return NO;  // If app crashed, never gets returned - should crash before that
    }
    

    NSLogAndHandleEveryExceptionMask flag告诉NSExceptionHandler捕获它所能捕获的每个异常(我相信仅适用于您的应用程序),而不管它在异常链的何处存在。

    这意味着 @终于抓住/@试试/@了 积木不起作用,因为 NSHandleOtherExceptionMask 标志告诉NSExceptionHandler在异常处理程序链上捕获“它下面的所有内容”。您可以删除该标志,但是HIToolKit可能会再次获得任何IBAction异常,因为它似乎位于所述链的较低位置。

    苹果的文档中有关于这些标志的信息: NSExceptionHandler docs

    因此,当引发NSException(应用程序AFAIK中的任意位置)并设置了NSLogAndHandleEveryExceptionMask时,代理中会按以下顺序调用这些异常:

    1. -exceptionHandler:shouldLogException:mask: 被称为第一。
    2. -exceptionHandler:shouldHandleException:mask: 被称为第二。

    只要把“崩溃代码”放在第二个委托方法中,就可以了。


    有用的文章: Understanding Exceptions and Handlers in Cocoa


    我认为让NSExceptionHandler的委托工作时遇到问题的原因是,它与设置为的自定义方法不兼容 NSSetUncaughtExceptionHandler() ,这是我上一个问题答案的一部分。每 Apple :

    NSExceptionHandler类提供 监测和监测设施 调试异常情况 Objective-C程序。它的工作原理是 异常处理程序通过 NSSetUncaughtExceptionHandler 功能。 因此,使用 NSExceptionHandler的服务,你 不得安装自己的自定义 未捕获的异常处理程序。

    -reportException: 方法。

    +initialize 与重写NSApplication的 -报告异常: 方法。

        2
  •  1
  •   Jens Ayton cdespinosa    14 年前