【问题标题】:How to catch NSInvalidArgumentException?如何捕获 NSInvalidArgumentException?
【发布时间】:2011-03-02 04:06:55
【问题描述】:

有什么办法可以抓住它吗?或者这是一个错误?

【问题讨论】:

  • 这不是一个错误,这是一个编程错误。不要将无效参数传递给方法,您将不会收到错误。它让你知道你做错了什么。
  • 嗯好吧 - 忘记添加的问题“或者这是一个错误”。我只想知道如何捕捉这个异常 NSInvalidArgumentException。

标签: objective-c exception-handling


【解决方案1】:

所以为了回答这个问题,我使用了以下内容:

@try{ 
   //your code
} @catch (NSException* exception) {
   NSLog(@"Got exception: %@    Reason: %@", exception.name, exception.reason);
}

并且字符串 NSInvalidArgumentException 被打印为 'exception.name',所以很明显,人们可以测试该 exception.name 的实际异常类型。

不是最漂亮的,但它确实有效。

【讨论】:

    【解决方案2】:

    如果我理解正确,您会问为什么无法捕获 NSInvalidArgumentsException。准确地说,即使您尝试将其捕获为 NSException,也不会捕获该异常,这应该始终有效。我也遇到了这个问题,环顾四周 - 这个问题确实看起来像苹果的错误。请参阅this page。人们在那里报告说该问题仅存在于模拟器上并且在真实设备上正常工作。

    【讨论】:

    • 在我的 Mac 10.7.5 环境中肯定会被捕获为 NSException。
    【解决方案3】:

    正如@David 所说,我们可以使用下面的代码

    @try{ 
       //your code
    } @catch (NSException* exception) {
       NSLog(@"Got exception: %@    Reason: %@", exception.name, exception.reason);
    }
    

    和@Moshe Kravchik 提到,有些情况下没有捕获到一些异常,主要是当我们在队列中调度新块时,所以我建议为每个队列调度添加单独的 try catch 块。

    即main()中的try..catch不会捕捉到AppDelegate类发生的异常,所以需要在AppDelegate中单独添加try..catch

    例如:

    - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
    {
        @try{
    
            self.viewController = [[MainViewController alloc] init];
    
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                @try{
                    NSLog(@"This is a block");
                    NSObject * b= nil;
                    [NSArray arrayWithObject:b];
                } @catch (NSException* exception) {
                    NSLog(@"Got exception: %@    Reason: %@", exception.name, exception.reason);
                }
            });
    
            return [super application:application didFinishLaunchingWithOptions:launchOptions];
        } @catch (NSException* exception) {
            NSLog(@"Got exception: %@    Reason: %@", exception.name, exception.reason);
        }
    }
    

    对于任何未捕获的异常,我们应该使用 NSSetUncaughtExceptionHandler,它不会阻止应用程序崩溃。

    void onUncaughtException(NSException* exception)
    {
        NSLog(@"onUncaughtException : %@", exception.reason);
    }
    
    int main(int argc, char* argv[])
    {
        @autoreleasepool {
            NSSetUncaughtExceptionHandler(&onUncaughtException);
            int retVal = UIApplicationMain(argc, argv, nil, @"AppDelegate");
             return retVal;
        }
    }
    

    对于除异常之外的信号,例如内存使用不当等,我们应该监听特定信号

    void signalHandler(int signal)
    {
        NSLog(@"Got signal %d",signal);
    }
    
        signal(SIGPIPE, &signalHandler);
        signal(SIGABRT, &signalHandler );
        signal(SIGHUP, &signalHandler );
        signal(SIGINT, &signalHandler );
        signal(SIGQUIT, &signalHandler );
        signal(SIGILL, &signalHandler );
        signal(SIGIOT, &signalHandler );
        signal(SIGFPE, &signalHandler );
        signal(SIGSEGV, &signalHandler );
        signal(SIGSYS, &signalHandler );
        signal(SIGPIPE, &signalHandler );
    

    关于未捕获异常here的更多详细信息。

    【讨论】:

    • 关于我的声明“不会阻止应用程序崩溃。”,它仅在调试时适用,实际运行时有机制继续,如cocoawithlove.com的参考链接中所示我的帖子。
    【解决方案4】:

    这是一个错误。具体来说,代码中的错误。 NSInvalidArgumentException 表示您已将错误数据传递给方法。这通常意味着您已将nil 作为不允许nil 的参数传递。异常描述应提供更多信息,说明哪些方法/参数不好。

    【讨论】:

    • 我只想能够捕捉到那个异常。我知道这意味着什么。
    • 这不是您捕获的那种异常。这是您确保一开始就不会抛出的那种异常。
    • 嗯,你让我有了不同的想法。好吧,如果有人知道如何捕捉它,那么请告诉我们,否则这是你一开始就无法捕捉到的东西,但就像凯文提到的那样防止。
    • 我认为这是错误的。例如,如果无法创建进程,则 NSTask 的启动方法会生成 NSInvalidArgumentException。无法创建进程的原因之一是它不存在或找不到。这不一定是编程错误。特别是,未捕获此异常将是一个编程错误。
    • 我和@PeterDeWeese 在同一个位置 当存档存在于磁盘上但不处于完美状态(即您进行了升级,文件已损坏)时,NSKeyedUnarchiver 可能会抛出此异常从您的应用程序的先前版本等)所有 I/O 代码总是有机会出错。您必须有办法处理这些错误情况。如果无法捕捉到,那我们就完蛋了。
    猜你喜欢
    • 1970-01-01
    • 2011-09-18
    • 2018-09-23
    • 1970-01-01
    • 1970-01-01
    • 2019-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多