Traitement rapide des erreurs pour les méthodes qui ne jettent pas [dupliquer]

Cette question a déjà une réponse ici:

comment gérer les erreurs pour les méthodes ou le code qui ne lance pas explicitement?

en l'Enveloppant d'un do / bloc catch résultats dans un avertissement du compilateur:

"'catch' block is unreachable because no errors are thrown in 'do' block"

venant de C# / Java background c'est une curiosité pour dire le moins. En tant que développeur, je devrais être capable de sauvegarder et d'envelopper n'importe quel bloc de code dans un bloc do/catch. Ce n'est pas parce qu'une méthode n'est pas explicitement marquée avec "Lancer" que des erreurs ne se produiront pas.

16
demandé sur rmaddy 2017-02-02 08:03:59

6 réponses

ce que vous demandez N'est pas possible dans Swift, étant donné que Swift n'a aucune facilité pour traiter les erreurs d'exécution telles que les hors limites, les violations d'accès ou les déballages forcés manqués pendant l'exécution. Votre demande prendra fin si l'une de ces graves erreurs de programmation se produit.

Quelques conseils:

pour faire court: ne faites pas de traitement des erreurs par raccourci dans Swift. Jouer en toute sécurité, toujours.

solution de contournement: si vous devez absolument attraper les erreurs runtime -, vous devez utiliser les limites du processus pour les garder. Exécuter un autre programme/processus et communiquer en utilisant des pipes, des douilles, etc.

6
répondu Christopher Oezbek 2017-07-23 20:03:17

je soupçonne que vous aimeriez attraper des erreurs qui ne sont pas explicitement marquées par "lancers".

enter image description here

Cela n'a aucun sens. Vous ne pouvez pas attraper autre chose que des erreurs qui sont explicitement marquées par "lancers". Cet avertissement est donc valable.

pour cet exemple, si exécuté,fatal error: Index out of range va se produire. C'est une erreur d'exécution, et vous ne pouvez pas l'attraper.

pour cet exemple, vous devriez vérifier la taille des éléments comme ceci, au lieu de faire des try-catch gestion des erreurs:

enter image description here

4
répondu mono 2017-07-24 14:12:15

il y a une différence entre les erreurs et les EXCEPTIONS. Swift ne traite que les erreurs qui sont explicitement lancées et n'a pas de capacité native pour traiter les EXCEPTIONS. Comme d'autres ont commenté des erreurs doivent être lancées et vous ne pouvez pas attraper ce qui n'est pas lancé.

par contraste objectif-C @try - @catch deal with exceptions, pas erreurs,. Certaines méthodes objc peuvent causer des exceptions mais ne les déclarent en aucune façon au compilateur. par exemple FileHandle.écrire. De telles exceptions sont plus étroitement alignées sur la version Java de RuntimeException qui n'a pas non plus besoin d'être déclarée.

il y a des situations comme la gestion de fichiers où il serait bon de gérer exceptions clairement dans Swift et c'est possible en utilisant une enveloppe Objective-C. Voir http://stackoverflow.com/questions/34956002/how-to-properly-handle-nsfilehandle-exceptions-in-swift-2-0

Code reproduit ici:

#ifndef ExceptionCatcher_h
#define ExceptionCatcher_h

#import <Foundation/Foundation.h>

NS_INLINE NSException * _Nullable tryBlock(void(^_Nonnull tryBlock)(void)) {
    @try {
        tryBlock();
    }
    @catch (NSException *exception) {
        return exception;
    }
    return nil;
}

#endif /* ExceptionCatcher_h */

puis l'appelant de Swift:

let exception = tryBlock {
   // execute dangerous code, e.g. write to a file handle
   filehandle.write(data)
}

if exception != nil {
   // deal with exception which is of type NSException
}
3
répondu Dale 2017-07-19 05:39:13

face à une exception lancée d'une méthode qui ne peut pas lancer. J'ai découvert que cette exception a été rejetée de l'objectif-c de L'API. Vous devriez donc l'attraper de manière ancienne en utilisant objective-C.

tout d'abord créer la classe objective-c qui prend plusieurs blocs dans la méthode init - pour essayer, attraper et finalement.

#import <Foundation/Foundation.h>

/**
 Simple class for catching Objective-c-style exceptions
 */
@interface ObjcTry : NSObject

/**
 *  Initializeer
 *
 *  @param tryBlock
 *  @param catchBlock
 *  @param finallyBlock
 *
 *  @return object
 */
- (_Nonnull id)initWithTry:(nonnull void(^)(void))tryBlock catch:(nonnull void(^)( NSException * _Nonnull exception))catchBlock finally:(nullable void(^)(void))finallyBlock;

@end

.m fichier:

#import "ObjcTry.h"

@implementation ObjcTry

- (_Nonnull id)initWithTry:(nonnull void(^)(void))tryBlock catch:(nonnull void(^)( NSException * _Nonnull exception))catchBlock finally:(nullable void(^)(void))finallyBlock
{
    self = [super init];
    if (self) {
        @try {
            tryBlock ? tryBlock() : nil;
        }
        @catch (NSException *exception) {
            catchBlock ? catchBlock(exception) : nil;
        }
        @finally {
            finallyBlock ? finallyBlock() : nil;
        }
    }
    return self;
}

@end

Deuxièmement, ajouter Ses en-têtes au fichier D'en-tête de Pont.

#import "ObjcTry.h"

et l'utiliser dans votre code swift comme ça:

var list: [MyModel]!
_ = ObjcTry(withTry: {
    // this method throws but not marked so, you cannot even catch this kind of exception using swift method.
    if let items = NSKeyedUnarchiver.unarchiveObject(with: data) as? [MyModel] {
         list = items
    }
}, catch: { (exception: NSException) in
    print("Could not deserialize models.")
}, finally: nil)
3
répondu Astoria 2017-07-22 16:05:50

Comme d'autres l'ont mentionné, vous ne devriez pas prendre ces erreurs, vous devez les corriger, mais si vous voulez exécuter plus de code avant la fin du programme, utilisez NSSetUncaughtExceptionHandlerAppDelegateapplicationdidFinishLaunchingWithOptions fonction.

la description de La fonction:

modifie le gestionnaire d'erreurs de niveau supérieur.

définit la gestion des erreurs de haut niveau fonction où vous pouvez effectuer une journalisation de dernière minute avant le programme se termine.

0
répondu inspector_60 2017-07-24 10:21:46

vous ne pouvez tout simplement pas. L'ensemble de l' do-try-catch ou do-catch l'instruction est destinée à être utilisée pour attraper les erreurs et...

je veux dire qu'il n'y a aucun intérêt à attraper une erreur si aucune erreur ne se produit en premier lieu... Je ne vois aucun scénario pourquoi voudriez-vous faire une telle chose, vous faites seulement compilateur fâché pour aucune raison.

c'est le même scénario si vous déballez en option avec if let ou guard let instructions

guard let smth = smthOpt?.moreSpecific else { return }

//Compiler gives warning -  unused variable smth. You wouldn't declare the variable and then not use it, or you would? 

simplement do-Catch n'est pas destiné à être utilisé pour utilisation sûre et je ne vois aucune raison de l'utiliser quand il ne s'agit pas d'opérations risquées qui ont besoin d'attraper...

pour plus de compréhension, voir:

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html

-2
répondu Dominik Bucher 2017-07-24 14:27:27