Verwendung von NSException in iPhone Apps

8

Einer meiner Freunde hat mich gebeten, NSException nicht in iPhone Apps zu verwenden. Der Grund, den er gab, war "Leistungsengpass". Aber davon bin ich nicht überzeugt.

Kann mir jemand bestätigen, dass wir davon absehen sollten, NSException in der iPhone App zu verwenden? Wenn Sie Best Practices für die Verwendung von NSException haben, geben Sie dies bitte ebenfalls an.

UPDATE:

Dies link fordert uns auf, die Ausnahmebehandlung auf App-Ebene zu verwenden. Hat es jemand jemals getan? Bitte geben Sie die Vorteile davon und andere Leistungshindernisse, die es schaffen könnte.

    
Krishnan 30.11.2010, 04:33
quelle

3 Antworten

30

Kurz gesagt:

Verwenden Sie keine Ausnahmen, um nur Fehler anzuzeigen, die nicht behebbar sind

Es ist nur angemessen, @ try / @ catch zu verwenden, um mit nicht behebbaren Fehlern umzugehen. Es ist nie angebracht, @ throw / @ try / @ catch zu verwenden, um Vorgänge wie unter iOS oder Mac OS X auszuführen. Achten Sie auch dann sorgfältig darauf, ob Sie eine Ausnahme verwenden, um einen nicht behebbaren Fehler anzuzeigen oder einfach abzustürzen ( Aufruf abbrechen ()); Ein Absturz hinterlässt oft signifikant mehr Beweise.

Zum Beispiel wäre es nicht sinnvoll, Ausnahmen zu erfassen, die außerhalb des zulässigen Bereichs liegen, es sei denn, Ihr Ziel besteht darin, sie zu erfassen und den Fehler irgendwie zu melden, dann - normalerweise - zu stürzen oder den Benutzer zumindest zu warnen Die App befindet sich in einem inkonsistenten Zustand und kann Daten verlieren.

Das Verhalten einer durch System-Framework-Code ausgelösten Ausnahme ist nicht definiert.

  

Können Sie das "Verhalten von jedem" erklären?   Ausnahme durch System ausgelöst   Framework - Code ist nicht definiert   Detail?

Sicher.

Die System-Frameworks verwenden ein Design, bei dem jede Ausnahme als ein schwerwiegender, nicht behebbarer Fehler betrachtet wird. ein Programmierfehler, für alle Absichten und Zwecke. Es gibt eine sehr begrenzte Anzahl von Ausnahmen (heh) zu dieser Regel.

Bei ihrer Implementierung stellen die Systemframeworks daher nicht sicher, dass alles ordnungsgemäß aufgeräumt wird, wenn eine Ausnahme ausgelöst wird, die den System-Framework-Code durchläuft. Sine die Ausnahme ist per Definition nicht wiederherstellbar, warum die Kosten für die Bereinigung bezahlen?

Betrachten Sie diesen Aufruf-Stack:

%Vor%

i.e. Code, in dem Ihr Code in Systemcode aufruft, der mehr von Ihrem Code aufruft (ein sehr häufiges Muster, obwohl die Callstacks offensichtlich deutlich tiefer sind).

Wenn your-code-2 eine Ausnahme auslöst, dass die Ausnahmen über system-code übergeben werden, bedeutet dies, dass das Verhalten nicht definiert ist. system-code kann oder kann Ihre Anwendung nicht in einem undefinierten, möglicherweise absturz- oder datenverlustbehafteten Zustand verlassen.

Oder, stärker: Sie können keine Ausnahme in your-code-2 werfen, mit der Erwartung, dass Sie sie in your-code-1 fangen und handhaben können.

    
bbum 30.11.2010, 07:59
quelle
6

Ich habe die Ausnahmebehandlung für meine ziemlich intensive Audio-App problemlos 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 ziemlich detailliert in dieser Blogpost , aber ich werde meine Ergebnisse hier skizzieren:

Mythos 1: @ try / @ catch / @ ist letztendlich zu teuer (in Bezug auf die 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 werfen?), 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?

Mythos 2: @try Blöcke kosten 32bit iOS

Die Apple-Dokumente sprechen von "null-kosten @try Blöcken auf 64bit " und geben an, dass 32 Bit Kosten verursachen. Eine kleine Benchmarking- und Disassemblierungsanalyse scheint darauf hinzuweisen, dass es auch bei 32bit iOS (ARM-Prozessor) kostensparende @try-Blöcke gibt. Wollte Apple 32bit Intel sagen?

Mythos 3: Es ist wichtig, dass Ausnahmen, die durch Cocoa Frameworks ausgelöst werden, nicht definiert sind

Ja, sie sind "undefiniert", aber was machst du eigentlich durch das Apple-Framework? Natürlich Apple behandelt sie nicht für Sie. Der ganze Sinn der Implementierung der Ausnahmebehandlung für behebbare Fehler besteht darin, sie lokal zu behandeln - nur nicht jede einzelne Zeile "lokal".

Ein Randfall 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 könnte es sein, dass Sie erwarten, dass die Ausnahme in Ihren aufrufenden Bereich übergeht. Zum Beispiel:

%Vor%

In diesem Fall würde die Ausnahme "durch das Kakaorahmenwerk" (die Laufschleife des Hauptthreads) gehen und Ihren Fang und Absturz verpassen. Sie können dies leicht umgehen, indem Sie GCD dispatch_synch verwenden und das Blockargument des Methodenaufrufs plus jede Ausnahmebehandlung verwenden.

Warum verwende NSException über NSError

Jeder, der jemals in einem der älteren C-basierten Frameworks wie Core Audio gearbeitet hat, weiß, was für eine lästige Aufgabe es ist, Fehler zu prüfen, zu verarbeiten und zu melden. Der Hauptvorteil von @ try / @ catch und NSExceptions ist, dass der Code sauberer und einfacher zu pflegen ist.

Angenommen, Sie haben 5 Codezeilen, 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 einzelne Zeile ein @try und behandeln Sie jeden Fehler direkt 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 das und weitere Details zu den Benchmarks und der Disassemblierung sind in diesem Blogbeitrag ...

Ausnahmen plus try / catch / finally ist das Paradigma, das von so ziemlich jeder anderen Hauptsprache verwendet wird (C ++, Java, PHP, Ruby, Python). Vielleicht ist es Zeit, die Paranoia fallen zu lassen und sie auch zu umarmen ... zumindest in iOS.

    
Hari Karam Singh 10.11.2012 12:16
quelle
0

Im Allgemeinen fragen Sie sich, wenn Sie versuchen, einen Fehler zu signalisieren, oder haben Sie tatsächlich eine außergewöhnliche Bedingung? Wenn der erste, dann ist es eine sehr schlechte Idee, unabhängig von einem Leistungsproblem, real oder wahrgenommen. Wenn Letzteres, ist es definitiv das Richtige zu tun.

    
jer 30.11.2010 04:36
quelle

Tags und Links