J'ai besoin d'implémenter une structure try-catch en Objective-C pour gérer les NSErrors lancés par Swift.
J'ai écrit un gestionnaire NetService avec du code Swift et je l'implémente sur une interface utilisateur Objective-C déjà existante.
/ p>
Cependant, chaque fois que je lance une erreur de ma classe Swift, la structure try-catch ne parvient pas à détecter l'erreur et passe au bloc finally.
Définition de l'erreur Swift:
2019-10-18 14:47:03.289268-0300 NEOFirmUpdate[16533:2389800] Start 2019-10-18 14:47:03.292696-0300 NEOFirmUpdate[16533:2389800] Finally
Erreur Swift lancée:
- (IBAction)pressUpdateButton:(id)sender { @try { [self.netServiceManager requestHelloPageAndReturnError: self.netServiceError]; } @catch (NSException *exception) { NSLog(@"Throwing"); } @finally { NSLog(@"Finally"); } }
Propriétés Objective-C:
@property NEONetServiceManager* netServiceManager; @property NSError* _Nullable __autoreleasing * _Nullable netServiceError;
Gestion des erreurs Objective-C:
@objc func requestHelloPage() throws { if serviceiPAddress != nil { makeHelloRequest() } else { throw NSError(domain: errorStrings.domain, code: NEONetServiceErrors.requestMadeWithoutIp.rawValue, userInfo:errorStrings.requestMadeWithoutIp) } }
Résultat:
enum NEONetServiceErrors: Int { case requestMadeWithoutIp } struct NEONetServiceErrorStrings { let requestMadeWithoutIp = ["NEONetService Error: Request made without IP": NEONetServiceErrors.requestMadeWithoutIp] }
Pourriez-vous m'aider à comprendre ce que je fais mal ma gestion des erreurs?
3 Réponses :
Le problème est qu'une erreur Swift / Objective-C NSError n'est pas une NSException. Vous êtes configuré pour intercepter NSExceptions mais cela n’a pas d’importance.
Le moyen de «capturer» une NSError dans Objective-C lorsque Swift lance une erreur est par indirection avec le paramètre NSError **
, tout comme cela a toujours été le cas.
NSError* err = nil; BOOL ok = [self.netServiceManager requestHelloPageAndReturnError:&err]; if (ok) { // proceed normally } else { // you got an error, it is sitting in `err` }
(Remarquez comment Swift fournit un résultat BOOL exactement pour que vous puissiez implémenter le modèle correct.)
Mon commentaire sur l'autre réponse s'applique également ici: les documents Apple indiquent que vous devez vérifier la valeur de retour pour le succès ou l'échec, avant d'essayer de faire quoi que ce soit avec l'objet NSError.
Oui @MartinR Je suis sur le point d'ajouter ça. L'OP n'a pas de valeur de retour, ce qui est un autre problème.
Cela est automatiquement traduit: @objc func requestHelloPage () throws
est importé dans Obj-C en tant que - (BOOL) requestHelloPageAndReturnError: (NSError * *) error;
C'est parce que vous utilisez des exceptions objective-c là-bas, et que vous ne recherchez pas une erreur. Pour vérifier les erreurs dans objective-c, vous passez une référence à votre pointeur et votre fonction remplira cette erreur s'il y avait un problème.
NSError *serviceError = nil; [self.netServiceManager requestHelloPage:^(NSError *error) { if (error) { // there was a problem } }];
S'il s'agit d'un appel asynchrone, vous ' Vous devrez le faire dans une fermeture à la place:
NSError *serviceError = nil; [self.netServiceManager requestHelloPageAndReturnError:&serviceError]; if (serviceError) { // there was a problem }
Ce n'est pas tout à fait correct. Vous toujours vérifiez d'abord la valeur de retour. Si c'est NON
(indiquant un échec) alors vous pouvez accéder à serviceError
.
Référence: developer.apple.com/libiberrer"> developer.apple.com archive / documentation / Cocoa /… : Important: le succès ou l'échec est indiqué par la valeur de retour de la méthode. Bien que les méthodes Cocoa qui renvoient indirectement des objets d'erreur dans le domaine d'erreur Cocoa soient garanties de renvoyer de tels objets si la méthode indique un échec en renvoyant directement nil ou NO, vous devez toujours vérifier que la valeur de retour est nil ou NO avant de tenter de faire quoi que ce soit avec le Objet NSError.
Dans quels cas avez-vous vu une erreur remplie mais une opération réussie?
Je ne l'ai pas «vu» car j'utilise toujours le modèle de vérification des erreurs documenté :)
Dans votre code Objective-C, vous attrapez et NSException, pas une NSError
Swift fait automatiquement le lien entre le type Error et le NSError classer. Les méthodes Objective-C qui produisent des erreurs sont importées en tant que Swift les méthodes qui lancent et les méthodes Swift qui lancent sont importées comme Méthodes Objective-C qui produisent des erreurs, selon Objective-C conventions d'erreur.
pour plus d'informations, vous pouvez cliquer sur ici