56 votes

Exceptions Objective-C

Je viens de terminer une application iPhone cours de programmation. Dans le cadre du cours, j'ai vu

  • Objective-C pour le traitement d'exception à l'aide de l' @try directive
  • Le système de bibliothèque n'a pas d'exception pour l'utilisation de la manipulation, préférant return nil

J'ai demandé si je doit utiliser la gestion des exceptions pour les nouveaux code que j'ai écrit (par exemple, si j'écris à la fois le front-end et le code de la logique, de sorte que la communication entre eux est dans mes mains) mais on m'a dit non, on ne devrait pas utiliser les exceptions pour le nouveau code. (Mais il a échoué à élaborer, puis la classe est déplacé, mais j'ai pensé que peut-être la raison serait clairement par la suite..)

Sûrement des exceptions sont supérieures à la return nil? Vous pouvez attraper des types particuliers, vous n'êtes pas tenté de l'ignorer en ignorant le type de retour d'une fonction qui réussit généralement, vous avez des messages texte qui peut être connecté, ils permettent à votre code pour se concentrer sur le cas normal, et donc d'être plus lisible. Pourquoi utiliser les exceptions.

Alors, qu'en pensez-vous? A été mon entraîneur droit de ne pas utiliser Objective-C des exceptions? Si oui, pourquoi?

69voto

zneak Points 45458

Il est dangereux de lancer des exceptions dans des circonstances où les ressources ne sont pas gérés automatiquement. C'est le cas de le Cacao cadre (et voisin des cadres), puisqu'ils utilisent le manuel de comptage de référence.

Si vous jeter une exception, tout release appel vous passez par dépiler entraînera une fuite. Cela devrait limiter les vous tothrowing uniquement si vous êtes certain que vous n'allez pas récupérer depuis toutes les ressources sont retournés à l'OS lorsqu'un processus se termine.

Malheureusement, NSRunLoops ont tendance à attraper toutes les exceptions qui se propagent à eux, donc, si vous jetez lors d'un événement, vous pourrez reprendre pour le prochain événement. C'est, évidemment, très mauvais. Par conséquent, il est préférable que vous simplement de ne pas le jeter.

Ce problème est diminuée si vous utilisez le garbage collector Objective-C, comme toute ressource représentée par un Objectif-C objet sera bien libérée. Cependant, C ressources (telles que les descripteurs de fichiers ou d' malloc-mémoire allouée) qui ne sont pas enveloppés dans un Objectif-C, l'objet sera toujours en fuite.

Donc, dans l'ensemble, de ne pas le jeter.

L'API Cocoa a plusieurs solutions de contournement pour cela, comme vous l'avez mentionné. De retour nil et de la NSError** modèle sont de deux d'entre eux.

Précisions pour l'ARC

ARC les utilisateurs peuvent choisir d'activer ou de désactiver de plein exception de sécurité. Lors de l'exception de sécurité est activé, l'ARC va générer du code pour la libération des références fortes lorsque leur portée est tué, ce qui le rend sûr à utiliser exception dans votre code. ARC aura pas de patch bibliothèques externes pour permettre à l'exception de soutien en eux, donc vous devez être prudent lorsque vous jeter (et surtout là où vous les attraper), même à l'exception de soutien activé dans votre programme.

ARC exception de soutien peut être activé avec -fobjc-arc-exceptions ou désactivée avec -fno-objc-arc-exceptions. Par défaut, il est désactivé en Objective-C, mais activé en Objective-C++.

Plein exception de sécurité en Objective-C est désactivée par défaut car le Bruit auteurs supposent que l'Objective-C programmes ne permettent pas de récupérer à partir d'une exception de toute façon, et parce qu'il est un grand de la taille du code de coûts et une petite perte de performance associés à ce nettoyage. En Objective-C++, d'autre part, le C++ introduit déjà beaucoup de nettoyage de code, et les gens sont beaucoup plus susceptibles de réellement besoin exception de sécurité.

C'est tout ce à partir de la spécification ARC sur le LLVM site web.

36voto

bbum Points 124887

Dans le Cacao et iOS programmeur, les exceptions sont utilisées pour indiquer la non-récupérables programmeur d'erreur. Lorsqu'une exception est levée par les cadres, il indique que les cadres ont détecté une erreur de l'état qui est à la fois non récupérable et pour lequel l'état interne est maintenant défini.

Ainsi, les exceptions levées par le biais de code de la structure de quitter les cadres de dans un état indéfini. I. e. vous ne pouvez pas faire quelque chose comme:

void a() {
    @throw [MyException exceptionWithName: @"OhNoes!"  ....];
}

@try {
    ... call into framework code that calls a() above ...
} @catch (MyException e) {
    ... handle e ...
}

Bas de ligne:

Les Exceptions ne doivent pas être utilisés dans le Cacao pour le contrôle de flux, la saisie de l'utilisateur de la validation, de la validité des données de détection ou d'indiquer recouvrable des erreurs. Pour cela, vous utilisez l' NSError** modèle comme indiqué ici (merci Abizem).

(Notez qu'il y a un petit nombre d'API qui ne violent -- où une exception est utilisé pour indiquer un état récupérable. Des Bugs ont été déposées contre ces à railler et à terme supprimer ces incohérences.)


Enfin trouvé le document que je recherche:

Important: Vous devriez réserver l'utilisation des exceptions pour la programmation ou des erreurs d'exécution inattendues telles que hors des limites d'un accès à une collection, les tentatives de muter des objets immuables, l'envoi d'un message non valide, et de perdre la connexion au serveur de fenêtre. Vous avez l'habitude de prendre soin de ces sortes des erreurs avec les exceptions lorsqu'une l'application est en cours de création plutôt que lors de l'exécution.

Si vous avez un corps de code (comme la troisième partie de la bibliothèque) utilise des exceptions pour gérer l'erreur conditions, vous pouvez utiliser le code comme-est dans votre application Cocoa. Mais vous devraient veiller à ce que toutes les des exceptions d'exécution n'échappent pas à la ces sous-systèmes et à la fin dans le l'appelant code. Par exemple, une analyse la bibliothèque peut utiliser les exceptions à l'interne pour indiquer des problèmes et permettre une sortie rapide à partir d'une analyse état qui pourraient être profondément récursive; cependant, vous devez prendre soin d'attraper de telles exceptions au plus haut niveau de la bibliothèque et de les traduire dans un code de retour approprié ou de l'état.

8voto

Abizern Points 52378

Je pense, et d'autres corrigez-moi si je me trompe, que les Exceptions doivent être utilisés pour intercepter les erreurs du développeur, tandis que l' NSError type d'erreur de manipulation doit être utilisé pour des conditions exceptionnelles qui se produisent pendant que le programme est en cours d'exécution.

Et comme pour le retour nil, ce n'est pas toutes les fonctions qui pourraient avoir des problèmes n'est pas juste de retour d'un nil, ils peuvent (et devraient) fournir de plus amples informations à l'aide de la NSError objet qui est transmis en tant que paramètre.

Voir aussi

3voto

JeremyP Points 46808

Personnellement, je ne vois aucune raison de ne pas utiliser les exceptions dans votre propre code. L'exception motif est plus propre pour les erreurs de manipulation de

  • toujours avoir une valeur de retour,
  • s'assurer que les valeurs de retour possibles signifie vraiment "erreur"
  • en passant un paramètre supplémentaire qui est une référence à un NSError*
  • saupoudrer votre code avec un nettoyage du code pour chaque retour en cas d'erreur ou d'avoir explicite gotos pour passer à une erreur commune de nettoyage de la section.

Toutefois, vous devez garder à l'esprit que d'autres personnes le code n'est pas garanti pour gérer exception correctement (si c'est de la pure C, en fait, il ne peut pas gérer les exceptions correctement). Donc, vous devez jamais, jamais, jamais autoriser une exception pour propager au-delà des limites de votre code. Par exemple, si vous jetez une exception profond dans les entrailles d'un délégué de la méthode, vous devez gérer cette exception avant de retourner à l'expéditeur du délégué message.

2voto

Evan Mulawski Points 28536

Le type d'erreur de manipulation utilisé dépend de ce que vous essayez d'accomplir. Presque tous de la Pomme de méthodes de remplir un NSError de l'objet qui peut être consulté à l'erreur.

Ce type d'erreur de manipulation peut être utilisé en conjonction avec un bloc try-catch au sein d'une section de code:

-(NSDictionary *)getDictionaryWithID:(NSInteger)dictionaryID error:(NSError **)error
{
    @try
    {
         //attempt to retrieve the dictionary
    }
    @catch (NSException *e)
    {
        //something went wrong
        //populate the NSError object so it can be accessed
    }
}

En un mot, le but de la méthode permet de déterminer le type d'erreur de manipulation, vous devriez utiliser. Mais, dans cet exemple ci-dessus, vous pouvez utiliser les deux.

Une utilisation courante pour le bloc try-catch:

@try
{
    [dictionary setObject:aNullObject forKey:@"Key"];
}
@catch (NSException *e)
{
    //one of the objects/keys was NULL
    //this could indicate that there was a problem with the data source
}

Espérons que cette aide.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X