Cannot access property on Swift type from Objective-C Cannot access property on Swift type from Objective-C objective-c objective-c

Cannot access property on Swift type from Objective-C


Optional values of non-Objective-C types aren't bridged into Objective-C. That is, the first three properties of TestClass below would be available in Objective-C, but the fourth wouldn't:

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}

In your Objective-C code, you'd access those first three properties like this:

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

In your case, you can either convert lat and long to be non-Optional or switch them to be instances of NSNumber.


Note that you need to be careful about your Objective-C code if you take the second approach (switching lat and lon to non-optional properties of type NSNumber) -- while the Swift compiler will prevent you from assigning nil to non-optional properties, the Objective-C compiler has no qualms about allowing it, letting nil values sneak into your Swift code with no chance of catching them at runtime. Consider this method on 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)    }}

This works fine if invoked with values in both of the properties, but if nsNumberVar is set to nil from the Objective-C code, this will crash at runtime. Note that there is no way to check whether or not nsNumberVar is nil before using it!

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


If your property is a Swift protocol type, just add @objc in front of it.

Example:

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


Optionals is a swift specific feature, not available in obj-c. Optional class instances work because a nil optional can be mapped to a nil value, but value types (int, floats, etc.) are not reference types, hence variable of those types don't store a reference, but the value itself.

I don't know if there's a solution - a possible workaround is creating non optional properties mapping the nil value to an unused data type value (such as -1 when representing an index, or 999999 for a coordinate):

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}

That should expose the _lat and _lon properties to obj-c.

Note that I have never tried that, so please let us know if it works.