tutorial tipos programación objective los lenguajes lenguaje entre diferencias datos caracteristicas básicos objective-c swift types objective-c-swift-bridge

objective-c - tipos - swift lenguaje de programación



No se puede acceder a la propiedad en tipo Swift desde Objective-C (4)

[ UInt? Int? o Double? propiedades] no se puede marcar @objc porque su tipo no se puede representar en Objective-C.

Sin embargo, es posible "ajustarlos" en un NSNumber así:

class Foo { var bar:Double? } // MARK: Objective-C Support extension Foo { /// bar is `Double?` in Swift and `(NSNumber * _Nullable)` in Objective-C @objc(bar) var z_objc_bar:NSNumber? { get { return bar as NSNumber? } set(value) { bar = value?.doubleValue ?? nil } } }

Estoy tratando de acceder a un Double? la clase Swift Double? propiedad de Objective-C.

class BusinessDetailViewController: UIViewController { var lat : Double? var lon : Double? // Other elements... }

En otro controlador de vista, estoy intentando acceder a lat siguiente manera:

#import "i5km-Swift.h" @interface ViewController () @property (strong, nonatomic) BusinessDetailViewController *businessDetailViewController; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.businessDetailViewController = [[BusinessDetailViewController alloc] initWithNibName:@"BusinessDetailViewController" bundle:nil]; self.businessDetailViewController.lat = businessArray[1]; /* THIS GIVES ME AN ERROR */ }

y estoy recibiendo

Propiedad ''lat'' no encontrada en el objeto de tipo ''BusinessDetailViewController *''

¿Por qué no puedo acceder a esta propiedad? ¿Qué me estoy perdiendo?


Los valores opcionales de los tipos que no son del Objective-C no están puenteados en Objective-C. Es decir, las tres primeras propiedades de TestClass continuación estarían disponibles en Objective-C, pero la cuarta no:

class TestClass: NSObject { var nsNumberVar: NSNumber = 0 // obj-c type, ok var nsNumberOpt: NSNumber? // optional obj-c type, ok var doubleVar: Double = 0 // bridged Swift-native type, ok var doubleOpt: Double? // not bridged, inaccessible }

En su código de Objective-C, accedería a las primeras tres propiedades como esta:

TestClass *optTest = [[TestClass alloc] init]; optTest.nsNumberOpt = @1.0; optTest.nsNumberVar = @2.0; optTest.doubleVar = 3.0;

En su caso, puede convertir lat y long para no ser opcionales o cambiarlos para que sean instancias de NSNumber .

Tenga en cuenta que debe tener cuidado con su código Objective-C si toma el segundo enfoque (conmutando lat y lon a propiedades no opcionales del tipo NSNumber ), mientras que el compilador Swift evitará que asigne nil a propiedades no opcionales. , el compilador de Objective-C no tiene reparos en permitírselo, permitiendo que valores nil entren sigilosamente en su código Swift sin posibilidad de atraparlos en el tiempo de ejecución. Considere este método en TestClass :

extension TestClass { func badIdea() { // print the string value if it exists, or ''nil'' otherwise println(nsNumberOpt?.stringValue ?? "nil") // non-optional: must have a value, right? println(nsNumberVar.stringValue) } }

Esto funciona bien si se invoca con valores en ambas propiedades, pero si nsNumberVar se establece en nil desde el código Objective-C, se bloqueará en el tiempo de ejecución. Tenga en cuenta que no hay forma de comprobar si nsNumberVar es nil o no antes de usarlo.

TestClass *optTest = [[TestClass alloc] init]; optTest.nsNumberOpt = @1.0; optTest.nsNumberVar = @2.0; [optTest badIdea]; // prints 1, 2 optTest.nsNumberOpt = nil; optTest.nsNumberVar = nil; [optTest badIdea]; // prints nil, then crashes with an EXC_BAD_ACCESS exception


Opcionales es una característica específica rápida, no disponible en obj-c. Las instancias de clase opcionales funcionan porque un nil opcional se puede asignar a un valor nulo, pero los tipos de valor (int, flotantes, etc.) no son tipos de referencia, por lo tanto, la variable de esos tipos no almacena una referencia, sino el valor mismo.

No sé si hay una solución: una posible solución es crear propiedades no opcionales mapeando el valor nil a un valor de tipo de datos no utilizado (como -1 al representar un índice, o 999999 para una coordenada):

class Test { var lat : Double? { didSet { self._lat = self.lat != nil ? self.lat! : 999999 } } var lon : Double? { didSet { self._lon = self.lon != nil ? self.lon! : 999999 } } var _lat: Double = 99999999 var _lon: Double = 99999999 }

Eso debería exponer las propiedades _lat y _lon a obj-c.

Tenga en cuenta que nunca lo he intentado, así que avísenos si funciona.


Si su propiedad es un tipo de protocolo Swift, simplemente agregue @objc en frente de él.

Ejemplo:

class Foo: UIViewController { var delegate: FooDelegate? ... } @objc protocol FooDelegate { func bar() }