бросить исключение в цель-с / какао - PullRequest
407 голосов
/ 27 ноября 2008

Какой лучший способ создать исключение в объективе-c / какао?

Ответы [ 13 ]

0 голосов
/ 09 ноября 2017

Пример кода для случая: @throw ([NSExceptionceptionWithName: ...

- (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

}

}

0 голосов
/ 30 июня 2014

Вы должны генерировать исключения только в том случае, если вы оказались в ситуации, которая указывает на ошибку программирования, и хотите остановить запуск приложения. Следовательно, лучший способ генерировать исключения - использовать макросы NSAssert и NSParameterAssert и убедиться, что NS_BLOCK_ASSERTIONS не определен.

0 голосов
/ 29 октября 2010

Нет никаких причин не использовать исключения, обычно в цели C, даже для обозначения исключений бизнес-правил. Apple может сказать, используйте NSError, кто заботится. Obj C существует уже давно, и когда-то ВСЯ документация C ++ говорила одно и то же. Причина, по которой не имеет значения, насколько дорого выбрасывать и перехватывать исключение, заключается в том, что время жизни исключения чрезвычайно мало и ... его ИСКЛЮЧЕНИЕ для обычного потока. Я никогда не слышал, чтобы кто-то говорил в моей жизни, что человеку, за исключением которого потребовалось много времени, чтобы его бросили и поймали.

Кроме того, есть люди, которые думают, что сама цель C слишком дорога, и вместо этого код на C или C ++. Поэтому, говоря, что всегда использовать NSError, плохо информирован и параноидален.

Но на вопрос этой темы еще не ответили, какой ЛУЧШИЙ способ вызвать исключение. Способы возврата NSError очевидны.

Так оно и есть: [повышение NSException: ... @throw [[выделение NSException] initWithName .... или @throw [[MyCustomException ...?

Здесь я использую проверенное / непроверенное правило немного иначе, чем выше.

Реальное различие между (используя метафору java здесь) проверенным / непроверенным важно -> можно ли восстановиться после исключения. И под выздоровлением я подразумеваю не просто НЕ крушение.

Поэтому я использую пользовательские классы исключений с @throw для восстанавливаемых исключений, потому что вероятно, у меня будет какой-то метод приложения, который ищет определенные типы сбоев в нескольких @ поймать блоки. Например, если мое приложение - банкомат, у меня будет блок @catch для "WithdrawalRequestExceedsBalanceException".

Я использую NSException: повышение для исключений времени выполнения, так как у меня нет способа восстановиться после исключения, кроме как поймать его на более высоком уровне и записать его. И нет никакого смысла в создании собственного класса для этого.

В любом случае, это то, что я делаю, но, если есть лучший, с таким же выразительным способом, я бы тоже хотел узнать. В моем собственном коде, так как я давно перестал кодировать C hella, я никогда не возвращаю NSError, даже если я передал его через API.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...