426 Stimmen

eine Ausnahme in objective-c/cocoa auslösen

Was ist der beste Weg, um eine Ausnahme in objective-c/cocoa zu werfen?

0voto

gnasher729 Punkte 49452

Sie sollten Ausnahmen nur dann auslösen, wenn Sie sich in einer Situation befinden, die auf einen Programmierfehler hindeutet, und die Ausführung der Anwendung stoppen wollen. Daher ist es am besten, Ausnahmen mit den Makros NSAssert und NSParameterAssert zu erzeugen und sicherzustellen, dass NS_BLOCK_ASSERTIONS nicht definiert ist.

0voto

Aleksandr B. Punkte 407

Beispielcode für den Fall: @throw([NSException exceptionWithName:...

- (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);
}

}

Verwenden:

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

Ein weiterer fortgeschrittener Anwendungsfall:

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

}

}

-6voto

deleted_user Punkte 3759

Es gibt keinen Grund, Ausnahmen nicht auch in Objective C zu verwenden, um Ausnahmen von Geschäftsregeln zu kennzeichnen. Apple kann sagen, benutze NSError, wen interessiert das. Objective C gibt es schon lange, und früher sagte die gesamte C++-Dokumentation dasselbe. Der Grund, warum es keine Rolle spielt, wie teuer das Werfen und Abfangen einer Ausnahme ist, ist, dass die Lebensdauer einer Ausnahme äußerst kurz ist und... es ist eine AUSNAHME zum normalen Ablauf. Ich habe noch nie in meinem Leben jemanden sagen hören: "Mann, diese Ausnahme hat aber lange gebraucht, um ausgelöst und abgefangen zu werden.

Es gibt auch Leute, die Objective C selbst für zu teuer halten und stattdessen in C oder C++ programmieren. Daher ist die Aussage, immer NSError zu verwenden, schlecht informiert und paranoid.

Aber die Frage dieses Threads wurde noch nicht beantwortet, was der beste Weg, um eine Ausnahme zu werfen. Die Möglichkeiten, NSError zurückzugeben, sind offensichtlich.

So ist es: [NSException raise:... @throw [[NSException alloc] initWithName.... oder @throw [[MyCustomException... ?

Ich verwende die Regel "angekreuzt/unangekreuzt" hier etwas anders als oben.

Der wirkliche Unterschied zwischen (hier wird die Java-Metapher verwendet) geprüft/ungeprüft ist wichtig --> ob Sie die Ausnahme beheben können. Und mit wiederherstellen meine ich nicht nur NICHT abstürzen.

Ich verwende also benutzerdefinierte Ausnahmeklassen mit @throw für wiederherstellbare Ausnahmen, weil es wahrscheinlich ist, dass ich eine App-Methode habe, die nach bestimmten Arten von Fehlern in mehreren @catch-Blöcke. Wenn meine Anwendung zum Beispiel ein Geldautomat ist, würde ich einen @catch-Block für die "WithdrawalRequestExceedsBalanceException".

Ich verwende NSException:raise für Laufzeitausnahmen, da ich keine Möglichkeit habe, die Ausnahme zu beheben, außer sie auf einer höheren Ebene abzufangen und zu protokollieren. Und theres keinen Sinn bei der Erstellung einer benutzerdefinierten Klasse für das.

Jedenfalls mache ich das so, aber wenn es eine bessere, ähnlich ausdrucksstarke Methode gibt, würde ich das auch gerne wissen. In meinem eigenen Code, seit ich aufgehört habe, C vor einer verdammt langen Zeit zu programmieren, gebe ich nie einen NSError zurück, selbst wenn ich einen von einer API übergeben bekomme.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X