Ich habe Ausnahmebehandlung für meine ziemlich intensive audio app ohne irgendwelche Probleme verwendet. Nach viel Lektüre und ein bisschen Benchmarking und Disassembly-Analyse bin ich zu der kontroversen Schlussfolgerung gekommen, dass es keinen wirklichen Grund gibt, sie (intelligent) nicht zu verwenden (NSError pointer-pointers, endless conditionals ...) juck!). Das meiste, was die Leute in den Foren sagen, ist nur die Apple Docs zu wiederholen.
Ich gehe in ziemlich viel Detail in this blog post aber ich werde meine Ergebnisse hier skizzieren:
Mythos 1: @ versuchen/@ catch/@ schließlich zu teuer ist (in Bezug auf CPU)
Auf meinem iPhone 4 dauert das Werfen und Fangen von 1 Million Ausnahmen etwa 8,5 Sekunden. Dies entspricht jeweils nur etwa 8,5 Mikrosekunden. Teuer in Ihrem Echtzeit-CoreAudio-Thread? Vielleicht ein bisschen (aber Sie würden niemals Ausnahmen dort hinwerfen?), Aber eine 8,5μs Verzögerung im UIAlert, die dem Benutzer mitteilt, dass es ein Problem beim Öffnen der Datei gab, wird es bemerkt werden?
Mythos 2: @try Blöcke eine Kosten auf 32-Bit-iOS
Die Apple-Docs „auf 64-Bit-Null-Kosten @try Blöcke“ von sprechen und erklären, dass 32-Bit eine Kosten entstehen. Eine kleine Benchmarking- und Disassemblierungsanalyse scheint darauf hinzuweisen, dass es auch bei 32bit iOS (ARM-Prozessor) kostensparende @try-Blöcke gibt. Wollte Apple sagen 32bit Intel?
Mythos 3: es wichtig ist, dass Geworfen Ausnahmen Durch Cocoa-Frameworks sind nicht definiert
Ja, sie sind „undefiniert“, aber was tun Sie über den Apple Rahmen zu werfen überhaupt? Natürlich Apple behandelt sie nicht für Sie. Der ganze Punkt der Implementierung der Ausnahmebehandlung für behebbare Fehler ist es, sie lokal zu behandeln - nur nicht jede einzelne Zeile "lokal".
Ein Rand Fall ist hier mit Methoden wie NSObject:performSelectorOnMainThread:waitUntilDone:
. Wenn der spätere Parameter JA ist, verhält sich das wie eine synchrone Funktion. In diesem Fall kann es passieren, dass Sie erwarten, dass die Ausnahme in Ihren aufrufenden Bereich übergeht. Zum Beispiel:
/////////////////////////////////////////////////////////////////////////
#pragma mark - l5CCThread
/////////////////////////////////////////////////////////////////////////
@interface l5CCThread : NSThread @end
@implementation l5CCThread
- (void)main
{
@try {
[self performSelectorOnMainThread:@selector(_throwsAnException) withObject:nil waitUntilDone:YES];
} @catch (NSException *e) {
NSLog(@"Exception caught!");
}
}
- (void)_throwsAnException { @throw [NSException exceptionWithName:@"Exception" reason:@"" userInfo:nil]; }
@end
/////////////////////////////////////////////////////////////////////////
#pragma mark - l5CCAppDelegate
/////////////////////////////////////////////////////////////////////////
@implementation l5CCAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
l5CCThread *thd = [[l5CCThread alloc] init];
[thd start];
return YES;
}
// ...
In diesem Fall wird die Ausnahme wäre „durch den Kakao Rahmen“ (der Haupt-Thread der Laufschleife) fehlt Ihren Fang und Absturz passieren. Sie können dies problemlos umgehen, indem Sie dispatch_synch
von GCD verwenden und das Methodenargument sowie jede Ausnahmebehandlung in sein Blockargument einfügen.
Warum verwenden NSException vorbei NSError der
Wer jemals Arbeit in einer der älteren C-basierten Frameworks wie Core Audio weiß, was eine lästige Pflicht es ist die Überprüfung, Handhabung und Fehler gemacht wird berichten. Der Hauptvorteil von @ try/@ catch und NSExceptions ist, dass der Code sauberer und einfacher zu pflegen ist.
Angenommen, Sie haben 5 Zeilen Code, die an einer Datei arbeiten. Jeder kann einen von, sagen wir, 3 verschiedenen Fehlern auslösen (z. B. nicht mehr genügend Speicherplatz, Lesefehler usw.). Anstatt jede Zeile in eine Bedingung einzufügen, die nach einem NEIN-Rückgabewert sucht und dann die NSError-Zeigeruntersuchung an eine andere ObjC-Methode auslagert (oder schlimmer noch, verwendet ein #define
Makro!), Wickeln Sie alle 5 Zeilen in eine einzige @try und Behandle jeden Fehler genau dort. Denken Sie an die Zeilen, die Sie speichern werden!
Durch das Erstellen von NSException-Unterklassen können Sie auch Fehlermeldungen problemlos zentralisieren und vermeiden, dass Ihr Code mit ihnen in Konflikt gerät. Sie können die "nicht-fatalen" Ausnahmen Ihrer Anwendung auch leicht von schwerwiegenden Programmierfehlern (wie NSAssert) unterscheiden. Sie können auch die Notwendigkeit für die "Name" -Konstante vermeiden (der Name der Unterklasse ist der "Name").
Beispiele für all dies und mehr Details zu dem Benchmarks und Demontage sind on this blog post ...
Ausnahmen und try/catch/finally das Paradigma von so ziemlich jede anderen großen Sprache (C++, Java, PHP verwendet wird, Ruby, Python). Vielleicht ist es an der Zeit, die Paranoia fallen zu lassen und sie auch zu umarmen ... zumindest in iOS.
Können Sie erklären, dass "das Verhalten einer Ausnahme, die durch den System-Framework-Code ausgelöst wird, nicht definiert ist." im Detail? – Krishnan
Aktualisiert die Frage .... – Krishnan
+1, Es ist schön one.Can Sie bitte sagen Sie mir meine Annahme in Bezug auf die Ausnahme ist nicht korrekt.Wenn ich NSException im Falle von bestimmten Ausnahme (Array außerhalb der Grenze) .dann es lädt alle Klassen für die Überprüfung der Ausnahme. Bitte antworten Sie. – Ishu