Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 如何阻止HIToolbox捕获我的异常?_Objective C_Cocoa_Exception Handling_Macos Carbon - Fatal编程技术网

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

Objective c 如何阻止HIToolbox捕获我的异常?,objective-c,cocoa,exception-handling,macos-carbon,Objective C,Cocoa,Exception Handling,Macos Carbon,这个问题是我另一个问题的后续问题 问题 当通过操作在主线程上引发异常时,应用程序仍然不会崩溃 根据,我在NSApplication上实现了reportException类别,并设置了未捕获的异常处理程序 代码 我的应用程序委托中有以下内容,我将其连接到UI中的一个按钮进行测试 -(IBAction)crashOnMainThread:(id)sender { [self performSelectorOnMainThread:@selector(crash) withObject:nil

这个问题是我另一个问题的后续问题

问题

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

根据,我在NSApplication上实现了reportException类别,并设置了未捕获的异常处理程序

代码

我的应用程序委托中有以下内容,我将其连接到UI中的一个按钮进行测试

-(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元素。很好

我已尝试在我的应用程序委托中使用以下命令安装自定义NSExceptionHandler:

-(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];
}
这里的问题是,无论捕获与否,每个异常都会崩溃

如果我尝试检查掩码,但没有在捕获的异常上崩溃,那么我将返回到第1步,因为HIToolbox似乎以与try/catch块完全相同的方式捕获异常

问题

  • 如何停止HIToolbox捕获异常,使我的应用程序使用未捕获的异常处理程序并崩溃
  • 运行与操作位于同一调用堆栈中的代码可以吗?这当然可以吗
  • 如果不行,还有什么办法

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

你不能信赖。除非有明确的文档记录,否则不支持跨API边界抛出异常(我想不出有任何案例有明确的文档记录)。

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

首先,撤销我在报告中提到的所有内容。出于某种原因,它不适用于IBActions。我的直觉是HIToolbox在异常处理链中处于较低的位置,并且在NSApplication有机会处理之前获取任何iAction/GUI异常。您可以使用
NSSetUncaughtExceptionHandler()
注册的任何自定义异常处理函数(我相信)都位于链的顶端

使用NSExceptionHandling,您的思路是正确的:

  • 将ExceptionHandling.framework添加到您的Xcode项目中
  • #将“ExceptionHandlerDelegate.h”导入AppDelegate.m(或自定义单例异常类)
  • 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
    标志告诉NSExceptionHandler捕获它可以捕获的每个异常(我相信,仅适用于您的应用程序),而不管它在异常链的何处

    这意味着@catch/@try/@finally块将不起作用,因为
    nshandleOtherExceptionTask
    标志告诉NSExceptionHandler捕获异常处理程序链上“它下面的所有内容”。您可以删除该标志,但HIToolKit可能会再次获得任何iAction异常,因为它似乎位于所述链的较低位置

    苹果的文档中有关于标志的信息:

    因此,当引发NSException(应用程序AFAIK中的任意位置)并设置NSLogandHandleeVeryeExceptionMask时,委托中会按顺序调用这些异常:

  • -首先调用exceptionHandler:shouldLogException:mask:
  • -exceptionHandler:shouldHandleException:mask:
    被称为second
  • 只需将“崩溃代码”放在第二个委托方法中,就可以了


    有用文章:


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

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

    当您重写NSApplication的
    -reportException:
    方法时,它也可能无法正常工作


    最后,似乎没有必要使用@catch/@try/@finally(这也是我之前回答的一部分)。在
    +initialize
    内部配置NSExceptionHandler似乎会立即“启动”,这与重写NSApplication的
    -reportException:
    方法不同。

    这很有意义。但在这种情况下,如果HIToolbox一直在我之前捕获异常,我如何在代码中捕获并报告异常?如果我想捕获异常,那么我不应该从同一线程运行代码作为操作,这一结论正确吗?我觉得这很奇怪。那么,还有什么选择呢?如果存在未捕获的异常,为什么您希望应用程序崩溃?这些异常会被捕获并记录下来,这样应用程序就不会崩溃。只需在
    [NSException raise]
    objc_exception_throw
    上设置一个断点即可调试异常,无需在此崩溃。对于正在调试的应用程序来说,这没问题。但是当它在生产过程中出现问题时呢?我希望我的应用程序在出现问题时立即崩溃,这样用户就可以报告它,我会意识到它(如果我还没有),然后马上修复它。仅供参考,这似乎不再是一个问题(macOS 10.14)。如果设置“[[NSUserDefaults standardUserDefaults]registerDefaults:@{@”NSApplicationCrashOnExceptions:@YES}]`