Les Exceptions Je suis un peu perdu avec NS_DURING, @try, @throw, @catch
Gercofis
Membre
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Donc la première chose à faire c'est d'ouvrir la doc Apple et chercher dedans les sujets qui parlent des Exceptions en Objective-C. Oh miracle, on y trouve ceci et aussi ceci, ça alors, quelle surprise... les as-tu lus ?
J'imagine que non, sinon tu aurais vu des remarques comme (pour @try, @catch, ...) ou (pour NS_DURING, etc) :
Il me semble que c'est un forum Français ?
Et si je parlais l'anglais je n'aurais pas forcément besoin de poser des questions ici ?
En plus de cela vu ma difficulté a capter ( ça vient peut-être de moi ) ce sysème des exceptions, dont personne ne parle, je pense aussi que ça peut intéressé d'autres, qui eux n'osent peut-être pas poser ce genre de question...
Ne ditons pas le ridicule ne tue pas !!
A noter que @catch n'est appelé qu'en cas d'exception et @finally dans tous les cas.
Quant à @trow, je ne ne vois pas bien à quoi il sert vu qu'on peut obtenir la même chose avec [exception raise].
Mais du coup a quoi sert NS_DURING, NS_HANDLER, etc...
C'est la même chose et ce sont des macros ? ou est-ce plus fait pour un emploi en local ?
Là dessus, sans vouloir enfoncer le clou, tu devrais relire la réponse de Ali. Sachant que "legacy" veut dire en gros: vieux machin.
Mais pour qu'un clou tienne il faut l'enfoncer...
En tous cas merci...
C'est quoi l'apport de @finally ? J'ai pas réussi à déterminer malgré une lecture attentive des pages...
Apparemment, ça :
et ça :
C'est pareil non ? Malgré des tests, je n'ai pas réussi à déterminer la différence entre les deux
Il a eu la gentillesse de consacrer une partie de son temps libre pour répondre à ta question, de rechercher et recopier pour toi les extraits pertinents dans la documentation. Alors je te prierais de te montrer plus courtois envers lui...
Y en a qui sont gonflés quand même.
C'est en effet un forum francophone, mais vu que:
1. l'anglais est incontournable pour qui veut progresser en cocoa;
2. les membres qui répondent aux questions le font sur leur temps libre et de ce fait on ne peut pas exiger d'eux qu'ils traduisent des textes écrits dans une langue incontournable pour le domaine qui est l'objet de ce forum;
3. il existe des outils de traduction automatique pour ceux qui ne comprennent vraiment pas l'anglais (qui devraient être une minorité, à cause du point 1.);
les réponses contenant des extraits de texte écrits en anglais sont tolérées et sont même préférées à pas de réponse du tout. De même que nous n'exigeons pas des membres qu'ils traduisent les pages web qu'ils renseignent dans des réponses.
On ne te demande pas de parler anglais, ni même de comprendre un film américain en version originale sans sous-titre. On te demande de comprendre un texte écrit en anglais technique.
Si tu veux pas apprendre le peu d'anglais nécessaire à la compréhension d'un document technique, c'est ton problème, mais ne t'en sers pas comme une excuse pour ne pas chercher et nous demander de faire ce boulot à ta place ou ignorer les réponses qui te sont proposées.
C'est pareil dans l'exemple que tu donnes. Mais dans ce genre de cas:
[tt]@try {
return;
}
@finally {
NSLog(@finally);
}[/tt]
ça ne l'est pas. Tu as la garantie que le code inclus dans le bloc @finally sera exécuté quoi qu'il arrive. Utile pour la gestion mémoire. Euh "quoi qu'il arrive" est peut être un peu excessif, mais bon, tu comprends l'idée.
OK, donc le "finally" sert à "clore" un "try" quand on ne veut pas mettre de "catch" (le compilateur gueule avec un "try" tout seul...)
Merci
Le @finally permet de mettre du code qui sera executé de toute façon, qu'il y ait eu une exception ou pas. Utile pour la gestion mémoire comme le dit Renaud.
Par exemple : Ici dans ce code je retourne NO s'il y a eu un problème quelquepart dans le code. Si je n'avais pas le @finally, il faudrait que je répète les lignes [tt][a release][/tt] et [tt][b release][/tt] à chaque fois avant un [tt]return NO;[/tt] pour libérer la mémoire avant de sortir. Ca fait des répétitions de code un peu inutiles.
Bon certes je pourrais mettre a et b en autorelease, mais bon c'est pour l'exemple.
Merci
L'exemple que tu donnes est peu probable en fait: si les méthodes appellées génèrent une exception, le return qui leur est associé ne sera pas exécuté, mais le controle passera directement dans le code @catch ...pour finalement aboutir à un return YES. Je reconnais aussi que mon exemple était un peu simpliste, son but était de montrer que le code de ce bloc était exécuté même dans des conditions où il n'aurait pas été exécuté normalement.
Un exemple plus réaliste aurait été:
[tt]a = [AClass new];
@try {
[a doSomething];
}
@catch (NSException *e) {
NSLog(@Something bad happened);
return NO;
}
@finalize {
// La directive @finalize permet d'éviter ici une redondance
// au niveau du post traitement
[a release];
}
...[/tt]
Bon ce cas en pratique n'est pas souvent rencontré, mais il en est un autre qui est du ressort des "nested exceptions" et qui lui est plus fréquent: on recrée une nouvelle exception dont le texte est plus approprié à la fonction exécutée, qu'on renvoie alors dans le système de gestion des exceptions. Et dans quel cas, la fonction courante perd aussi le contrôle et donc il peut en résulter des fuites mémoires sans le @finalize. C'est le cas qui est présenté dans la doc.
Effectivement, fort utile pour les "nested exceptions" ! (même si on peut s'en tirer sans avec des redondances...)
Bah non justement, quand une exception est levée, tout ce qui est après le @try et hors du @catch utilisé ou du @finally ne sera pas exécuté, c'est pour ça qu'il y a le @finally, la fin de la fonction n'est pas exécutée. Donc il faudrait faire ce genre de truc :
Donc je pense qu'il vaudrait mieux faire ce genre de code
Ensuite pour répondre à la question à savoir : à quoi sert l'instruciton @throw alors qu'on peut écrire [monException raise] ?
Il existe pour deux raisons essentiellement, d'abord pour permettre l'écriture, plus en rapport avec les autres instructions et moins lourds en terme d'envoi de message, de ce genre de truc : @throw [NSException exceptionWithName: NSGenericException reason: @It crashed man ! userInfo: nil];
Mais aussi et surtout parce que tu peux lever autre chose que des objets héritant de NSException. La forme canonique de l'utilisation des exceptions c'est ça :
Notez que si après le finally il y a des traitements à faire sur les objets si tout s'est bien passé, on peut envoyer le message -autorelease plutôt que -release pour éviter de bousiller le code qui suit.
Il faut aussi remarquer que l'instruction @throw peut permettre aussi au compilateur de faire des optimisations.
Pour ceux qui se poseraient la question, à savoir : comment on fait pour connaà®tre la raison de l'exception lorsqu'il s'agit d'un objet de type id quelconque ?
Vous pouvez par exemple utiliser la méthode -description qui est disponible à tous les objets respectant le procotole NSObject, de cette façon :