2009-04-12 2 views
9

Рассмотрим следующие какао/Obj-C фрагменты кода:В каких обстоятельствах @finally не является избыточным в Cocoa's try/catch/finally Exception Handling?

MyClass *obj; 
@try { 
    [obj doSomething]; 
} 
@catch (NSException * e) { 
    NSLog(@"Exception occurred: %@", [e description]); 
} 
@finally { 
    [obj cleanUp]; 
} 

и

MyClass *obj; 
@try { 
    [obj doSomething]; 
} 
@catch (NSException * e) { 
    NSLog(@"Exception occurred: %@", [e description]); 
} 
[obj cleanUp]; 

В чем будет первый результат сниппет в [obj cleanUp] Называние обстоятельств, в то время как второй не будет результат в [obj cleanUp] называется? Другими словами, при каких обстоятельствах @finally не является избыточным при использовании обработки исключений Cocoa?

ответ

5

В этом случае, когда вы раздавите исключение, ничего. @finally используется для очистки, когда вы либо не поймаете исключение, либо не свернете его, в любом случае, оставляя окончательный ответ на вызов вызывающему коду. Поскольку исключения в какао только предполагается использовать для программирования ошибок и, следовательно, происходят редко, это вполне разумно.

Это также стоит отметить один случай, когда вы не нужно необходимо использовать @finally, то есть когда вы создали свой собственный пул авторефератов. Когда «родительский» пул авторесурсов будет уничтожен, все внутренние, которые еще не были очищены, также будут. Если вы попытаетесь очистить его самостоятельно, вам необходимо продвинуть исключение из своего пула автообновлений.

+1

FYI, здесь подробно описывается, как выполнять управление памятью с помощью команды @ try/@ catch/@ throw/@ finally: http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ Исключения/Задачи/HandlingExceptions.html # // apple_ref/doc/uid/20000059-SW7 –

1

Когда:

  • Вы не ловя тип исключения, что произошедший
  • Вы поймали исключение, но код в блоке улова также вызывает исключение.
15

В этих сценариях нет разницы, поскольку исключение проглатывается. Вот два сценария, где является разница:

[OBJ Cleanup] называется:

MyClass *obj; 
@try { 
    [obj doSomething]; 
} 
@catch (NSException * e) { 
    @throw;  
} 
@finally { 
    [obj cleanUp]; // called when exception is caught 
} 

[OBJ Cleanup] не называется:

MyClass *obj; 
@try { 
    [obj doSomething]; 
} 
@catch (NSException * e) { 
    @throw; 
} 
[obj cleanUp]; // not called when exception is caught 
0

Более низкий уровень вопрос, почему ты это делаешь?

Метод try/catch/finally широко используется в Java, но почти никогда не используется в Objective-C, и не является предпочтительным подходом - вам просто не нужно, поскольку библиотеки не будут генерировать исключения, как вызовы библиотеки Java , и если вы пишете свои собственные библиотеки, вы не должны ожидать, что абоненты, естественно, подумают, что искать исключения для улова.

Наиболее широко используемым и понятным является соглашение делегата, у которого есть обратный вызов метода ошибки или, возможно, уведомления для более общих сбоев, которые необходимо пройти через несколько уровней кода. Этот подход может быть более широко использован в мире Java, если бы существовала простая система уведомлений, как она была создана Какао.

Подход делегата имеет то же свойство документирования, что и объявление исключения в Java, но это просто разные подходы, но обычно лучше использовать подход, более подходящий к языку под рукой, если нет особого основания для этого.

+0

В настоящее время я работаю с try/catch/наконец, поскольку Apple Scripting Bridge в OS X 10.5 регулярно терпит неудачу, бросая исключения. Если вы используете Scripting Bridge, вы не можете избежать исключений. Я полностью согласен, что для большинства кода Cocoa/Objective-C исключения не являются лучшим способом обработки ошибок. –

7

Стоит также отметить, что код в @finally блоков будет работать, когда управление выходит из блока @tryпо какой-либо причине, даже через return или goto. Например:

@try { 
    doStuff(); 
    if(bail){ 
     return; 
    } 
    doMoreStuff(); 
} 
@finally { 
    [obj cleanUp]; 
} 
[obj announceSuccess]; 

[obj cleanUp] будет выполняться, даже если bail верно, но [obj announceSuccess] не будет.