代码之家  ›  专栏  ›  技术社区  ›  Steph Thirion

在objective-c/cocoa中引发异常

  •  402
  • Steph Thirion  · 技术社区  · 16 年前

    在objective-c/cocoa中引发异常的最佳方式是什么?

    13 回复  |  直到 7 年前
        1
  •  532
  •   cwharris    12 年前

    我用 [NSException raise:format:] 详情如下:

    [NSException raise:@"Invalid foo value" format:@"foo of %d is invalid", foo];
        2
  •  258
  •   Ben Lings    14 年前

    这里有一句警告的话。在Objective-C中,与许多类似的语言不同,您通常应该避免在正常操作中可能发生的常见错误情况下使用异常。

    Apple's documentation for Obj-C 2.0

    Apple's conceptual Exception handling documentation

    this explanation .

        3
  •  62
  •   Cœur Gustavo Armenta    5 年前
    @throw([NSException exceptionWith…])
    

    Xcode识别 @throw return 声明。使用 @扔 控件可能会到达非void函数的末尾 “您可能从 [NSException raise:…] .

    而且 @扔 可用于抛出不属于NSException类的对象。

        4
  •  33
  •   Cœur Gustavo Armenta    5 年前

    [NSException raise:format:] . 对于那些来自Java背景的人,您会记得Java区分了异常和RuntimeException。异常是选中的异常,而RuntimeException是未选中的。特别是,Java建议对“正常错误条件”使用检查异常,对“程序员错误导致的运行时错误”使用未检查异常。似乎Objective-C异常应该在使用未检查异常的相同位置使用,在使用选中异常的地方,最好使用错误代码返回值或N错误值。

        5
  •  15
  •   rustyshelf    16 年前

    我认为为了保持一致,最好在扩展NSException的类中使用@throw。然后对try-catch-finally使用相同的符号:

    @try {
    .....
    }
    @catch{
    ...
    }
    @finally{
    ...
    }
    

    苹果在这里解释了如何抛出和处理异常: Catching Exceptions Throwing Exceptions

        6
  •  14
  •   Psycho    15 年前

    无论如何,断言(使用NSAssert和NSCASERT宏系列)抛出NSException,因此可以将它们用作Ries状态。

        7
  •  8
  •   NANNAV gngrwzrd    12 年前

    使用NSError来传达故障,而不是异常。

    有关N错误的快速要点:

    参考链接: Reference

        8
  •  8
  •   Johannes    11 年前

    这是我从“大书呆子牧场指南(第四版)”中学到的:

    @throw [NSException exceptionWithName:@"Something is not right exception"
                                   reason:@"Can't perform this operation because of this or that"
                                 userInfo:nil];
    
        9
  •  6
  •   Subbu    12 年前

    可以使用两种方法在try-catch块中引发异常

    @throw[NSException exceptionWithName];
    

    还是第二种方法

    NSException e;
    [e raise];
    
        10
  •  3
  •   edwardmp    9 年前

    我相信您永远不应该使用异常来控制正常的程序流。但是当某个值与所需值不匹配时,应该抛出异常。

    里斯

        11
  •  0
  •   gnasher729    11 年前

        12
  •  0
  •   Aleksandr B.    7 年前

    案例的示例代码:@throw([NSException Exception Exception WithName:。。。

    - (void)parseError:(NSError *)error
           completionBlock:(void (^)(NSString *error))completionBlock {
    
    
        NSString *resultString = [NSString new];
    
        @try {
    
        NSData *errorData = [NSData dataWithData:error.userInfo[@"SomeKeyForData"]];
    
        if(!errorData.bytes) {
    
            @throw([NSException exceptionWithName:@"<Set Yours exc. name: > Test Exc" reason:@"<Describe reason: > Doesn't contain data" userInfo:nil]);
        }
    
    
        NSDictionary *dictFromData = [NSJSONSerialization JSONObjectWithData:errorData
                                                                     options:NSJSONReadingAllowFragments
                                                                       error:&error];
    
        resultString = dictFromData[@"someKey"];
        ...
    
    
    } @catch (NSException *exception) {
    
          NSLog( @"Caught Exception Name: %@", exception.name);
          NSLog( @"Caught Exception Reason: %@", exception.reason );
    
        resultString = exception.reason;
    
    } @finally {
    
        completionBlock(resultString);
    }
    

    }

    [self parseError:error completionBlock:^(NSString *error) {
                NSLog(@"%@", error);
            }];
    

    另一个更高级的用例:

    - (void)parseError:(NSError *)error completionBlock:(void (^)(NSString *error))completionBlock {
    
    NSString *resultString = [NSString new];
    
    NSException* customNilException = [NSException exceptionWithName:@"NilException"
                                                              reason:@"object is nil"
                                                            userInfo:nil];
    
    NSException* customNotNumberException = [NSException exceptionWithName:@"NotNumberException"
                                                                    reason:@"object is not a NSNumber"
                                                                  userInfo:nil];
    
    @try {
    
        NSData *errorData = [NSData dataWithData:error.userInfo[@"SomeKeyForData"]];
    
        if(!errorData.bytes) {
    
            @throw([NSException exceptionWithName:@"<Set Yours exc. name: > Test Exc" reason:@"<Describe reason: > Doesn't contain data" userInfo:nil]);
        }
    
    
        NSDictionary *dictFromData = [NSJSONSerialization JSONObjectWithData:errorData
                                                                     options:NSJSONReadingAllowFragments
                                                                       error:&error];
    
        NSArray * array = dictFromData[@"someArrayKey"];
    
        for (NSInteger i=0; i < array.count; i++) {
    
            id resultString = array[i];
    
            if (![resultString isKindOfClass:NSNumber.class]) {
    
                [customNotNumberException raise]; // <====== HERE is just the same as: @throw customNotNumberException;
    
                break;
    
            } else if (!resultString){
    
                @throw customNilException;        // <======
    
                break;
            }
    
        }
    
    } @catch (SomeCustomException * sce) {
        // most specific type
        // handle exception ce
        //...
    } @catch (CustomException * ce) {
        // most specific type
        // handle exception ce
        //...
    } @catch (NSException *exception) {
        // less specific type
    
        // do whatever recovery is necessary at his level
        //...
        // rethrow the exception so it's handled at a higher level
    
        @throw (SomeCustomException * customException);
    
    } @finally {
        // perform tasks necessary whether exception occurred or not
    
    }
    

    }

        13
  •  -7
  •   deleted_user    14 年前

    此外,有人认为目标C本身太贵,而C或C++中的代码则相反。所以说总是使用N错误是不明智和偏执的。

    我在这里使用的选中/未选中规则与上面的略有不同。

    检查/取消检查(此处使用java比喻)之间的真正区别很重要-->是否可以从异常中恢复。我所说的恢复不仅仅是指不崩溃。

    因此,我将自定义异常类与@throw一起用于可恢复异常,因为 我可能会有一些应用程序方法来查找多个应用程序中的某些类型的故障 “提款请求超出余额例外”。

    我对运行时异常使用NSException:raise,因为我无法从异常中恢复,

    无论如何,这就是我所做的,但如果有更好的,类似的表达方式,我也想知道。在我自己的代码中,因为我很久以前就停止编写C代码了,所以即使API向我传递了一个N错误,我也不会返回N错误。