gpt4 book ai didi

cocoa - 为什么引发 NSException 不会导致我的应用程序崩溃?

转载 作者:行者123 更新时间:2023-12-03 16:04:29 27 4
gpt4 key购买 nike

问题

我正在编写一个 Cocoa 应用程序,我想引发异常,从而使应用程序崩溃。

我的应用程序委托(delegate)中有以下几行:

[NSException raise:NSInternalInconsistencyException format:@"This should crash the application."];
abort();

问题是,他们不会关闭应用程序 - 消息只是记录到控制台,应用程序会继续正常运行。

据我了解,异常(exception)的全部意义在于他们在特殊情况下被解雇。在这些情况下,我希望应用程序以明显的方式退出。但这并没有发生。

我尝试过的

我已经尝试过:

-(void)applicationDidFinishLaunching:(NSNotification *)note
// ...
[self performSelectorOnMainThread:@selector(crash) withObject:nil waitUntilDone:YES];
}

-(void)crash {
[NSException raise:NSInternalInconsistencyException format:@"This should crash the application."];
abort();
}

这不起作用,

-(void)applicationDidFinishLaunching:(NSNotification *)note
// ...
[self performSelectorInBackground:@selector(crash) withObject:nil];
}

-(void)crash {
[NSException raise:NSInternalInconsistencyException format:@"This should crash the application."];
abort();
}

令人困惑的是,它按预期工作。

发生什么事了?我做错了什么?

最佳答案

更新 - 2010 年 11 月 16 日:当 IBAction 方法内引发异常时,此答案存在一些问题。请参阅此答案:

How can I stop HIToolbox from catching my exceptions?

<小时/>

这扩展了David Gelhar的回答以及他提供的链接。下面是我通过重写 NSApplication 的 -reportException: 方法来完成此操作的方法。首先,为 NSApplication 创建一个 ExceptionHandling 类别(仅供引用,您应该在“ExceptionHandling”之前添加 2-3 个字母的缩写,以减少名称冲突的风险):

NSApplication+ExceptionHandling.h

#import <Cocoa/Cocoa.h>

@interface NSApplication (ExceptionHandling)

- (void)reportException:(NSException *)anException;

@end

NSApplication+ExceptionHandling.m

#import "NSApplication+ExceptionHandling.h"

@implementation NSApplication (ExceptionHandling)

- (void)reportException:(NSException *)anException
{
(*NSGetUncaughtExceptionHandler())(anException);
}

@end
<小时/>

其次,在 NSApplication 的委托(delegate)内部,我执行了以下操作:

AppDelegate.m

void exceptionHandler(NSException *anException)
{
NSLog(@"%@", [anException reason]);
NSLog(@"%@", [anException userInfo]);

[NSApp terminate:nil]; // you can call exit() instead if desired
}

- (void)applicationWillFinishLaunching:(NSNotification *)aNotification
{
NSSetUncaughtExceptionHandler(&exceptionHandler);

// additional code...

// NOTE: See the "UPDATE" at the end of this post regarding a possible glitch here...
}

您可以调用 exit(),而不是使用 NSApp 的 terminate:terminate: 更符合 Cocoa-kosher,尽管您可能希望在抛出异常时跳过 applicationShouldTerminate: 代码,并使用 exit( ):

#import "sysexits.h"

// ...

exit(EX_SOFTWARE);
<小时/>

每当在主线程上抛出异常时,并且该异常未被捕获和销毁,现在将调用您的自定义未捕获异常处理程序,而不是 NSApplication 的异常处理程序。这允许您使应用程序崩溃,等等。

<小时/>

更新:

上面的代码似乎有一个小错误。在 NSApplication 完成调用其所有委托(delegate)方法之前,您的自定义异常处理程序不会“启动”并工作。这意味着,如果您在 applicationWillFinishLaunching:applicationDidFinishLaunching:awakeFromNib: 中执行一些设置代码,默认的 NSApplication 异常处理程序将出现在- 播放直到完全初始化。

这意味着如果您这样做:

- (void)applicationWillFinishLaunching:(NSNotification *)aNotification
{
NSSetUncaughtExceptionHandler(&exceptionHandler);

MyClass *myClass = [[MyClass alloc] init]; // throws an exception during init...
}

您的exceptionHandler不会得到异常。 NSApplication 会,并且它只会记录它。

要解决此问题,只需将任何初始化代码放入 @try/@catch/@finally block 中,您就可以调用自定义的 exceptionHandler:

- (void)applicationWillFinishLaunching:(NSNotification *)aNotification
{
NSSetUncaughtExceptionHandler(&exceptionHandler);

@try
{
MyClass *myClass = [[MyClass alloc] init]; // throws an exception during init...
}
@catch (NSException * e)
{
exceptionHandler(e);
}
@finally
{
// cleanup code...
}
}

现在您的 exceptionHandler() 获取异常并可以相应地处理它。 NSApplication 完成调用所有委托(delegate)方法后,NSApplication+ExceptionHandling.h 类别启动,通过其自定义的 -reportException: 方法调用ExceptionHandler()。此时,当您希望将异常引发到未捕获的异常处理程序时,您不必担心 @try/@catch/@finally。

我对造成这种情况的原因有点困惑。可能是 API 中幕后的东西。即使我对 NSApplication 进行子类化,而不是添加类别,也会发生这种情况。可能还有其他警告。

关于cocoa - 为什么引发 NSException 不会导致我的应用程序崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3336278/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com