Swift ne convertit pas Objective-C NSError ** en jets

J'ai un code hérité Objective-C, qui déclare une méthode comme

- (void)doSomethingWithArgument:(ArgType)argument error:(NSError **)error 

Comme écrit ici https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html

Swift traduit automatiquement les methods Objective-C qui génèrent des erreurs dans les methods qui émettent une erreur en fonction de la fonctionnalité de gestion des erreurs natives de Swift.

Mais dans mon projet, les methods décrites sont appelées comme ceci:

 object.doSomething(argument: ArgType, error: NSErrorPointer) 

De plus, il lance une exception d'exécution lorsque j'essaie de les utiliser comme:

 let errorPtr = NSErrorPointer() object.doSomething(argumentValue, error: errorPtr) 

Ai-je besoin de quelque chose de plus pour convertir les methods Objective-C "NSError **" en methods "trows" Swift?

Seules les methods Objective-C qui returnnent un BOOL ou un object (nullable) sont traduites en methods de lancement dans Swift.

La raison en est que les methods Cocoa utilisent toujours une valeur de return NO ou nil pour indiquer l'échec d'une méthode, et pas seulement pour définir un object d'erreur. Cela est documenté dans Utilisation et création d'objects d'erreur :

Important: Le succès ou l'échec est indiqué par la valeur de return de la méthode. Bien que les methods Cocoa qui renvoient indirectement des objects d'erreur dans le domaine d'erreur Cocoa soient garanties pour renvoyer ces objects si la méthode indique un échec en renvoyant directement nil ou NO, vous devez toujours vérifier que la valeur de return est nulle ou nulle avant de tenter quoi que ce soit. Objet NSError

Par exemple, l'interface Objective-C

 @interface OClass : NSObject NS_ASSUME_NONNULL_BEGIN -(void)doSomethingWithArgument1:(int) x error:(NSError **)error; -(BOOL)doSomethingWithArgument2:(int) x error:(NSError **)error; -(NSSsortingng *)doSomethingWithArgument3:(int) x error:(NSError **)error; -(NSSsortingng * _Nullable)doSomethingWithArgument4:(int) x error:(NSError **)error; NS_ASSUME_NONNULL_END @end 

est mappé à Swift comme

 public class OClass : NSObject { public func doSomethingWithArgument1(x: Int32, error: NSErrorPointer) public func doSomethingWithArgument2(x: Int32) throws public func doSomethingWithArgument3(x: Int32, error: NSErrorPointer) -> Ssortingng public func doSomethingWithArgument4(x: Int32) throws -> Ssortingng } 

Si vous pouvez changer l'interface de votre méthode, vous devez append une valeur de return booleanne pour indiquer le succès ou l'échec.

Sinon, vous l'appelleriez de Swift comme

 var error : NSError? object.doSomethingWithArgument(argumentValue, error: &error) if let theError = error { print(theError) } 

Remarque: A

J'ai trouvé que Clang a un atsortingbut qui force une fonction à lancer une erreur dans Swift:

 -(void)doSomethingWithArgument5:(int) x error:(NSError **)error __atsortingbute__((swift_error(nonnull_error))); 

est mappé à Swift comme

 public func doSomethingWithArgument5(x: Int32) throws 

et semble fonctionner "comme prévu". Cependant, je n'ai trouvé aucune documentation officielle sur cet atsortingbut, ce n'est donc pas une bonne idée de m'en remettre.

Vous devez faire en sorte que votre méthode renvoie un BOOL , pour indiquer à l'exécution qu'une erreur doit ou ne doit pas être générée. De plus, vous devez append __autoreleasing au paramètre error pour vous assurer que ARC ne relâche pas accidentellement l'erreur avant de pouvoir l'utiliser:

 - (BOOL)doSomethingWithArgument:(ArgType)argument error:(NSError * __autoreleasing *)error 

Vous pouvez ensuite l'appeler de Swift comme ceci:

 do { object.doSomethingWithArgument(someArgument) } catch let err as NSError { print("Error: \(err)") }