Używanie obsługi wyjątków w porównaniu z NSError w aplikacjach Cocoa

Cześć wszystkim. Czytałem na temat sugestii Apple, kiedy / gdzie / jak używać NSError kontra @ try / @ catch / @ wreszcie. Zasadniczo mam wrażenie, że Apple uważa, że ​​najlepiej jest unikać stosowania konstrukcji języka obsługujących wyjątki, z wyjątkiem mechanizmu zatrzymania wykonywania programu w nieoczekiwanych sytuacjach błędu (może ktoś mógłby podać przykład takiej sytuacji?)

Pochodzę z Javy, gdzie wyjątki są sposobem na to, aby poradzić sobie z błędami. Wprawdzie nadal jestem w przestrzeni myśliwskiej Java, ale powoli zajmuję się wszystkim, co NSError ma do zaoferowania.

Jedną rzeczą, którą się rozłączam, jest czyszczenie pamięci, gdy wystąpi błąd. W wielu sytuacjach (np. Przy użyciu bibliotek C, C ++, CoreFoundation itd.) Masz dużo czyszczenia pamięci, które należy wykonać przed przerwaniem funkcji z powodu błędu.

Oto przykład, który przygotowałem dokładnie odzwierciedlający sytuacje, z którymi się spotkałem. Używając wyimaginowanych struktur danych, funkcja otwiera uchwyt pliku i tworzy obiekt „MyFileRefInfo”, który zawiera informacje o tym, co zrobić z plikiem. Niektóre rzeczy są robione z plikiem przed zamknięciem uchwytu pliku i zwolnieniem pamięci dla struktury. Korzystając z sugestii Apple mam tę metodę:

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

}

Teraz .. moja logika Java mówi mi, że lepiej byłoby ustawić to jako strukturę try / catch / finally i umieścić wszystkie wywołania, aby zamknąć uchwyt pliku i zwolnić pamięć w bloku finally.

Tak jak ..

    ...

    @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;

Czy szaleję myśląc, że jest to bardziej eleganckie rozwiązanie z mniej zbędnym kodem? Przegapiłem coś?

questionAnswers(4)

yourAnswerToTheQuestion