Question

J'ai quelques doutes concernant la gestion des exceptions dans l'iPhone. Les voici:

  1. Supposons que j'ai une chaîne de méthodes qui sont appelées les unes après les autres, c'est-à-dire que la méthode A appelle la méthode B, qui à son tour appelle la méthode C, qui appelle la méthode D. Quel est le meilleur endroit pour mettre mon bloc try-catch (est-ce la méthode A ou B ou C ou D ou tous). De plus, je dois afficher une alerte à l'utilisateur indiquant qu'une exception s'est produite, puis je souhaite enregistrer cette exception sur mon serveur. Donc, si j'écris mon bloc try - catch dans toutes ces méthodes et si une exception se produit dans la méthode D; alors je pense que l'alerte sera affichée 4 fois et le service Web pour la journalisation sera également appelé 4 fois (jusqu'à ce que le contrôle atteigne pour attraper le bloc de la méthode A). Alors, devrais-je simplement utiliser @throw; dans le bloc catch des méthodes B, C et D et écrivez ma logique dans le bloc catch de la méthode A (méthode de niveau supérieur) ou devrais-je éviter d'écrire try - catch du tout dans les méthodes B, C et D.

  2. J'ai besoin d'une sorte de code d'erreur de l'exception (car mon service Web a besoin de paramètres code d'erreur et description). Est-il possible de convertir une exception en erreur ou dois-je coder ce code en dur?

  3. J'avais lu quelque part sur NSSetUncaughtExceptionHandler. Et je pense que si je peux définir ce gestionnaire (dans la méthode appDidFinishLaunching du délégué d'application) et dans la méthode du gestionnaire, si je montre à l'utilisateur une alerte et appelle le service Web; alors je n'ai pas besoin d 'écrire le bloc try - catch dans chacune de mes méthodes, dans chacune de mes classes. Ai-je raison ??

  4. Si une exception s'est produite et que j'ai écrit un bloc try-catch ou NSSetUncaughtExceptionHandler, mon application continuera à s'exécuter ou elle ne répondra à aucun des événements utilisateur. (Je suis sûr qu'il gérera le plantage. Ce que je veux savoir, c'est s'il va se bloquer)

Quelqu'un s'il vous plaît m'éclairer sur ce SUJET D'EXCEPTION.

Était-ce utile?

La solution

0) Évitez les exceptions dans Cocoa. Ils ne sont généralement pas récupérables. Vous pourriez les attraper pour votre propre rapport d'erreurs, mais il n'est généralement pas sûr de supposer que vous pouvez les récupérer.

1) Si vous avez besoin d'attraper, attrapez-le immédiatement . N'écrivez pas vos propres lancers , convertissez-le plutôt en quelque chose comme un NSError et transmettez-le. NSError peut contenir toutes les informations dont vous avez besoin pour afficher ou envoyer un code d'erreur ainsi qu'un message localisé.

2) Vous ne pouvez pas convertir un NSException en un NSError (directement) car un NSException n'a pas toutes les propriétés d'un NSError - c'est une représentation de données différente. D'une part, un code d'erreur n'est pas disponible. Deuxièmement, la description n'est pas localisée. Le mieux que vous puissiez faire est de créer un code d'erreur et un domaine, puis d'utiliser les propriétés dont vous avez besoin du NSException et de les stocker dans un NSError. Cela pourrait ressembler à ceci:

// error checking omitted
extern NSString* const MONExceptionHandlerDomain;
extern const int MONNSExceptionEncounteredErrorCode;

NSError * NewNSErrorFromException(NSException * exc) {
    NSMutableDictionary * info = [NSMutableDictionary dictionary];
    [info setValue:exc.name forKey:@"MONExceptionName"];
    [info setValue:exc.reason forKey:@"MONExceptionReason"];
    [info setValue:exc.callStackReturnAddresses forKey:@"MONExceptionCallStackReturnAddresses"];
    [info setValue:exc.callStackSymbols forKey:@"MONExceptionCallStackSymbols"];
    [info setValue:exc.userInfo forKey:@"MONExceptionUserInfo"];

    return [[NSError alloc] initWithDomain:MONExceptionHandlerDomain code:MONNSExceptionEncounteredErrorCode userInfo:info];
}

@catch (NSException * exc) {
    NSError * err = NewNSErrorFromException(exc);
    ...
}

Si les API que vous utilisez lèvent des exceptions dont vous êtes censé récupérer et récupérer (par exemple, des cas pas vraiment exceptionnels), alors oui, vous pouvez attraper et tenter de continuer. Malheureusement, quiconque écrit des exceptions dans Cocoa avec l'intention de les attraper ne comprend probablement pas assez bien les problèmes pour implémenter une implémentation de déroulement solide (par exemple, même si cela produit des fuites, ce n'est pas solide).

3) Ce n'est vraiment ni le moment ni le lieu pour afficher une alerte. Si vous installez un gestionnaire d'exceptions de niveau supérieur (via NSSetUncaughtExceptionHandler) - Vous devez simplement consigner un message - alors le gestionnaire d'exceptions abandonnera. Votre application est dans un état instable - continuer est pire qu'annuler. Vous voudrez peut-être envoyer ces messages personnalisés à la maison, il est préférable de le faire lors du prochain lancement de votre application.

4) Dans la majorité des cas, votre application est dans un état instable et vous ne devriez pas continuer. Mais, pour y répondre réellement pour ces cas de figure: "Oui, vous pouvez récupérer et continuer lorsque vous attrapez, mais vous ne devriez essayer de récupérer et de continuer que lorsque l'API de lancement indique que la récupération est prise en charge. Si le problème est indépendant de votre volonté, et le problème n'est pas exceptionnel (par exemple, fichier non trouvé), et le vendeur s'attend vraiment à ce que vous continuiez, alors je devrais supposer qu'il s'attend à ce que vous continuiez, même si ce n'est vraiment pas (100% sûr). ". N'essayez pas de récupérer / continuer à partir de votre gestionnaire d'exceptions de niveau supérieur (le programme abandonnera après son retour). Si vous voulez être très sophistiqué et le présenter immédiatement sur OSX, un autre processus serait préférable. Si vous appelez via une interface C ++ pure, le déroulement est bien défini et le besoin de capture est nécessaire - continuez s'il est récupérable. Les exceptions en C ++ peuvent être récupérables et bien définies - elles sont également utilisées de manière assez intensive (y compris des conditions moins qu'exceptionnelles).

(IMO ...) Les exceptions dans ObjC ne devraient pas avoir été introduites, et toute méthode qui émet des bibliothèques système ou tierces devrait être obsolète. Ils ne se détendent pas bien ou d'une manière bien définie. De plus, le déroulement des flux par rapport au flux normal du programme Cocoa. Cela signifie que toucher la mémoire / les relations d'un objet objc qui était en mutation au moment du lancer et qui se trouve entre le lancer et la capture est aussi bon qu'un comportement indéfini. Le problème est que vous n'avez aucune idée de ce qu'est cette mémoire (dans la plupart des cas, et dans un délai de maintenance raisonnable). Les exceptions C ++ sont bien définies et se déroulent correctement (par exemple, les destructeurs sont appelés) - mais essayer de continuer dans un contexte ObjC revient à ignorer les conséquences d'un comportement non défini. IMO, ils ne devraient exister que pour ObjC ++ (car C ++ les requiert).

Dans un monde idéal, vos programmes ObjC et les bibliothèques que vous utilisez n'utiliseraient pas d'exceptions (du tout). Puisque vous utilisez des bibliothèques qui lancent (y compris Cocoa), inst

tous un gestionnaire d'exceptions de niveau supérieur uniquement si vous avez besoin d'informations spéciales sur l'erreur .Lorsque l'API exige que vous puissiez vous attendre à une exception levée en raison de circonstances indépendantes de votre volonté et que vous êtes censé récupérer , écrivez une capture mais convertissez immédiatement cette logique en flux de programme normal (par exemple, NSError) - vousjamais besoin d'écrire votre propre lancer.-[NSArray objectAtIndex: et "objet ne répond pas au sélecteur" sont des exemples d'erreurs de programmeur - elles ne devraient pas être détectées, mais le programme devrait être corrigé.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top