Mithilfe der Exception-Behandlung versus NSError in Cocoa-Apps
Hey alle. Ich habe gelesen, bis auf Apple ' s Vorschläge für Wann/wo/wie zu verwenden NSError versus @try/@catch/@endlich. Im wesentlichen habe ich den Eindruck, dass Apple denkt, dass es am besten zu vermeiden, die Verwendung von exception-handling-Konstrukte, außer als ein Mechanismus zum anhalten der Programmausführung in unerwarteten Fehlersituationen (vielleicht könnte jemand ein Beispiel geben für so eine situation?)
Ich komme von Java, wo Ausnahmen sind der Weg zu gehen, wenn man will, Fehler zu behandeln. Zugegeben, ich bin noch in der Java-thoughtspace, aber ich bin langsam in den Griff mit allen, die NSError zu bieten hat.
Eins ist mir hängen geblieben ist die Aufgabe der Reinigung mit dem Speicher, wenn ein Fehler Auftritt. In vielen Situationen (z.B. unter Verwendung von C, C++ Bibliotheken, CoreFoundation, etc..) und Sie haben eine Menge von Speicher-Bereinigung, die getan werden, vor dem ausbrechen einer Funktion aufgrund eines Fehlers.
Hier ist ein Beispiel, das ich zusammengebraut, die genau spiegelt die Situationen habe ich seit der Begegnung. Über einige imaginäre Datenstrukturen, die Funktion öffnet sich ein Datei-handle, und erstellt eine 'MyFileRefInfo' - Objekt, das Informationen darüber enthält, was mit der Datei machen. Einige Sachen geschieht mit der Datei, bevor die Datei-handle geschlossen und der Speicher für das struct befreit. Mit Apple ' s Vorschläge habe ich diese Methode:
- (BOOL)doSomeThingsWithFile:(NSURL *)filePath error:(NSError **)error
{
MyFileReference inFile; //Lets say this is a CF struct that opens a file reference
MyFileRefInfo *fileInfo = new MyFileRefInfo(...some init parameters...);
OSStatus err = OpenFileReference((CFURLRef)filePath ,&inFile);
if(err != NoErr)
{
*error = [NSError errorWithDomain:@"myDomain" code:99 userInfo:nil];
delete fileInfo;
return NO;
}
err = DoSomeStuffWithTheFileAndInfo(inFile,fileInfo);
if(err != NoErr)
{
*error = [NSError errorWithDomain:@"myDomain" code:100 userInfo:nil];
CloseFileHandle(inFile); //if we don't do this bad things happen
delete fileInfo;
return NO;
}
err = DoSomeOtherStuffWithTheFile(inFile,fileInfo);
if(err != NoErr)
{
*error = [NSError errorWithDomain:@"myDomain" code:101 userInfo:nil];
CloseFileHandle(inFile); //if we don't do this bad things happen
delete fileInfo;
return NO;
}
CloseFileHandle(inFile);
delete fileInfo;
return YES;
}
Nun.. meine Java-Logik sagt mir, dass es besser wäre, diese Einrichtung, wie ein try/catch/finally-Struktur und legen Sie alle Anrufe, um zu schließen Sie die Datei-handle-und der freie Speicher auf der finally-block.
Wie so..
...
@try
{
OSStatus err = OpenFileReference((CFURLRef)filePath ,&inFile);
if(err != NoErr)
{
... throw some exception complete with error code and description ...
}
err = DoSomeStuffWithTheFileAndInfo(inFile,fileInfo);
if(err != NoErr)
{
... throw some exception ...
}
... etc ...
}
@catch(MyException *ex)
{
*error = [NSError errorWithDomain:@"myDomain" code:[ex errorCode] userInfo:nil];
return NO;
}
@finally
{
CloseFileHandle(inFile); //if we don't do this bad things happen
delete fileInfo;
}
return YES;
Bin ich verrückt zu denken, dass dies ist eine viel elegantere Lösung mit weniger redundanten code?
Hab ich was verpasst?
- Das Beispiel kann vereinfacht ein bisschen, aber vergessen Sie nicht zu überprüfen, dass der Fehler nicht NULL ist, bevor Sie Sie zuweisen, da die Konvention ist das senden von NULL anstelle des Fehler-variable, wenn Sie kümmern sich nicht um Fehler. Wenn Sie dereferenzieren von NULL-in diesem Fall, Sie werden zu einem bus-Fehler (es ist nicht so, messaging ein null-Objekt).
Du musst angemeldet sein, um einen Kommentar abzugeben.
Daniel ' s Antwort ist richtig, aber diese Frage verdient eine eher stumpfe Antwort.
Werfen eine exception, wenn ein nicht behebbarer Fehler ist aufgetreten.
Verwenden NSError bei der Kommunikation von Fehlerzuständen, die eventuell wiederhergestellt werden.
Ausnahme, die ausgelöst wird durch einen Rahmen in Apple ' s frameworks möglicherweise nicht definiertes Verhalten zur Folge.
Es ist ein Ausnahmen Programmierung Thema Dokument verfügbar im dev center.
Das ist nicht so ganz mein Eindruck. Ich dachte, dass Apple schlägt vor, die Ausnahmen für die wirklich außergewöhnlichen Bedingungen, und NSError für erwartete Ausfälle. Seit Sie kommen aus Java, ich denke, NSError -> java.lang.Ausnahme, und Obj-C Ausnahmen -> java.lang.RuntimeException. Verwenden Sie eine Obj-C-Ausnahme, wenn die Programmierer etwas falsch gemacht (verwendet eine API falsch, zum Beispiel), und verwenden Sie NSError, wenn ein erwarteter Fehler ist aufgetreten (dem remote-server nicht gefunden werden konnte, zum Beispiel).
Natürlich, das ist nur meine interpretation von apples position. Ich, auf der anderen Seite, wie die Ausnahmen!!!
Ausnahmen in Objective-C haben in der Vergangenheit bereits 'schwer', mit einer Leistungseinbuße zu betreten eines try-Blocks, Kosten zu werfen, um Kosten für die Nutzung schließlich, etc. Als Ergebnis Cocoa-Entwickler haben in der Regel vermieden Ausnahmen außerhalb von 'oh Nein, der Himmel fällt' möglichen Situationen-wenn eine Datei fehlt, verwenden Sie einen NSError, aber wenn es kein Dateisystem und einen negativen Betrag von Speicher frei, das ist eine Ausnahme.
Das ist die historische Sicht. Aber wenn Sie eine 64-bit-app auf 10.5 oder höher, Ausnahme-Architektur wurde umgeschrieben, um die "null-Kosten", die bedeuten, dass die historische Ansicht ist nicht mehr relevant. Wie mit gerade ungefähr allem, kommt es auf verschiedene Faktoren -- wenn man Weg ist natürlicher, und Sie werden lassen Sie schneller fertig, und wenn Sie nicht irgendwelche performance-Probleme mit ihm, und wenn etwas inkonsistent mit 'traditionellen' Objective-C-code, der Sie nicht stört... dann gibt es keinen Grund, nicht zu verwenden, Ausnahmen.
Laut
More iPhone 3 Development
von Dave Mark und Jeff LeMarche, Ausnahmen sind nur für die wirklich außergewöhnlichen Situationen und in der Regel auf ein problem in Ihrem code. Sie sollten niemals Ausnahmen zu berichten, ein run-of-the-mill-Fehler. Exceptions werden verwendet, mit viel weniger Frequenz in Objective-C als in vielen anderen Sprachen, wie Java und C++.Sie eine Ausnahme, wenn Sie brauchen, um einen Fehler in Ihrem code. Verwenden Sie eine Fehlermeldung, wenn der Benutzer müssen möglicherweise das problem zu beheben.
Hier ist ein Beispiel, wo würden Sie eine Ausnahme:
Schreiben wir eine Unterklasse, und wir wollen sicherstellen, dass Ihre Unterklassen die Implementierung eines bestimmten Methode. Objective-C keine abstrakten Klassen, und es fehlt ein Mechanismus zu zwingen, eine Unterklasse zu implementieren, die eine bestimmte Methode. Aber wir können eine Ausnahme zu sofort uns informieren, dass wir vergessen haben zu implementieren Sie die Methode in einer Unterklasse. Statt einem unvorhersehbaren Verhalten, wir bekommen schlug mit einem Laufzeit-exception. Wir können leicht Debuggen, da unser Ausnahme sagen uns genau, was wir falsch gemacht haben:
Da problem ist ein Programmierer Fehler eher als ein problem der Benutzer kann in der Lage zu beheben, verwenden wir eine Ausnahme.