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).
InformationsquelleAutor | 2010-01-05
Schreibe einen Kommentar