ios objective-c swift nserror

ios - Swift no convierte Objective-C NSError** en lanzamientos



(2)

Tengo un código heredado de Objective-C, que declara el método como

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

Tal como está escrito aquí https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html

Swift traduce automáticamente los métodos de Objective-C que producen errores en métodos que generan un error de acuerdo con la funcionalidad de manejo de errores nativa de Swift.

Pero en mi proyecto los métodos descritos se llaman así:

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

Además, lanza una excepción de tiempo de ejecución cuando trato de usarlos como:

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

¿Necesito algo más para convertir los métodos "NSError **" de Objective-C en métodos "trows" rápidos?


Debe hacer que su método devuelva un BOOL , para indicar al tiempo de ejecución que se debe o no lanzar un error. También debe agregar __autoreleasing al parámetro de error, para asegurarse de que ARC no libere accidentalmente el error antes de que tenga la oportunidad de usarlo:

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

Entonces puedes llamarlo desde Swift así:

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


Solo los métodos Objective-C que devuelven un objeto BOOL o un objeto (que puede contener nulos) se convierten a métodos de lanzamiento en Swift.

La razón es que los métodos Cocoa siempre usan un valor de retorno NO o nil para indicar el fallo de un método, y no solo para establecer un objeto de error. Esto se documenta en Uso y creación de objetos de error :

Importante: el éxito o el fracaso se indica mediante el valor de retorno del método. Aunque los métodos Cocoa que indirectamente devuelven objetos de error en el dominio de error Cocoa tienen la garantía de devolver tales objetos si el método indica un error devolviendo directamente nil o NO, siempre debe verificar que el valor de retorno sea nil o NO antes de intentar hacer algo con Objeto NSError.

Por ejemplo, la interfaz de Objective-C

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

se asigna a Swift como

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

Si puede cambiar la interfaz de su método, debe agregar un valor de retorno booleano para indicar el éxito o el fracaso.

De lo contrario lo llamarías desde Swift como

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

Observación: en

Encontré que Clang tiene un atributo que obliga a una función a lanzar un error en Swift:

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

se asigna a Swift como

public func doSomethingWithArgument5(x: Int32) throws

y parece funcionar "como se esperaba". Sin embargo, no pude encontrar ninguna documentación oficial sobre este atributo, por lo que podría no ser una buena idea confiar en él.