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ś?