2009-04-12 6 views
9

Tenir compte des extraits suivants du code Cocoa/Obj-C:Dans quelles circonstances @finally n'est-il pas redondant dans la procédure d'exception try/catch/finally de Cocoa?

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

et

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

Dans quelles circonstances le premier résultat de bout en [obj cleanUp] appelé, alors que le second ne sera pas résultat au [obj cleanUp] étant appelé? En d'autres termes, dans quelles circonstances @finally n'est-il pas redondant lors de l'utilisation de Cocoa Exception Handling?

Répondre

5

Dans ce cas, où vous écrasez l'exception, aucun. @finally est utilisé pour nettoyer lorsque vous ne capturez pas l'exception ou que vous la renvoyez, dans les deux cas, en laissant une réponse d'exception finale au code appelant. Puisque les exceptions dans Cocoa ne sont censées être utilisées que pour des erreurs de programmation et se produisent rarement, c'est une chose tout à fait raisonnable à faire.

Il est également intéressant de souligner un cas où vous besoin d'utiliser @finally, ce qui est lorsque vous configurez votre propre pool autorelease. Lorsque le pool autorelease "parent" est détruit, tous ceux internes qui n'ont pas encore été nettoyés le seront également. Si vous essayez de le nettoyer vous-même, vous devez promouvoir l'exception elle-même hors de votre pool autorelease.

+1

FYI, voici le document d'Apple détaillant comment gérer la mémoire avec @ try/@ catch/@ throw/@ enfin la gestion des exceptions: http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ Exceptions/Tâches/HandlingExceptions.html # // apple_ref/doc/uid/20000059-SW7 –

1

Quand:

  • Vous ne rattrapent pas le type d'exception qui a eu lieu
  • Vous avez attrapé l'exception, mais le code dans le bloc catch soulève également une exception.
15

Dans ces scénarios, il n'y a pas de différence car l'exception est avalée. Voici deux scénarios où est une différence:

[obj cleanUp] est appelé:

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

[obj cleanUp] n'est pas appelé:

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

Une question de niveau inférieur, pourquoi fais-tu ça? L'approche try/catch/finally est largement utilisée en Java mais rarement utilisée en Objective-C, et n'est pas une approche préférée - vous n'en avez tout simplement pas besoin car les bibliothèques ne lèveront pas d'exceptions comme les appels de bibliothèque Java et si vous écrivez vos propres bibliothèques, vous ne devriez pas vous attendre à ce que les appelants pensent naturellement à rechercher des exceptions à attraper. La convention la plus largement utilisée et comprise est celle d'un délégué qui a un rappel de méthode d'erreur, ou peut-être des notifications pour des échecs plus généraux que vous devez transmettre à travers plusieurs niveaux de code. Cette approche pourrait être plus largement utilisée dans le monde Java s'il existait un système de notification simple comme Cocoa l'a mis en place. L'approche déléguée a la même propriété de documentation que la déclaration d'une exception dans Java, ce ne sont que des approches différentes mais il est généralement préférable d'utiliser une approche plus adaptée à la langue à moins qu'il y ait une raison très convaincante.

+0

Je travaille actuellement avec try/catch/finally puisque le Scripting Bridge d'Apple dans OS X 10.5 échoue régulièrement en lançant des exceptions. Si vous utilisez Scripting Bridge, vous ne pouvez pas éviter les exceptions. Je suis tout à fait d'accord, pour la plupart des codes Cocoa/Objective-C, les exceptions ne sont pas la meilleure façon de traiter les erreurs. –

7

Il est également intéressant de noter que le code dans @finally blocs fonctionnera lorsque le contrôle sort du bloc @trypour une raison quelconque, même via return ou goto. Par exemple:

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

[obj cleanUp] exécutera même si bail est vrai, mais [obj announceSuccess] seront pas.

Questions connexes