Unable to access Swift property from Objective-C

I am trying to call var swift from c object class. What am I doing as below:

Class swift

class BusinessDetailViewController: UIViewController { var lat : Double? var lon : Double? @IBOutlet var mapView: MKMapView? override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) // Here you can init your properties } required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } 

In ViewController.m, I try to call lat as follows:

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

and i get

 Property 'lat' not found on object of type 'BusinessDetailViewController *' 

Any ideas on which I cannot access, or I am missing something else.

+47
ios objective-c swift
Oct 14 '14 at 16:50
source share
3 answers

Additional values ​​of non-Objective-C types are not bound to Objective-C. That is, the first three properties of TestClass below will be available in Objective-C, but the fourth will not:

 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 Objective-C code, you get access to these first three properties, for example:

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

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




Note that you need to be careful with your Objective-C code if you take the second approach (switching lat and lon to optional properties like NSNumber ) - while the Swift compiler will prevent you from assigning nil to optional properties, the Objective compiler- C has no doubt about its resolution, allowing nil values ​​to creep into your Swift code without any 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 great when calling values ​​in both properties, but if nsNumberVar set to nil from Objective-C code, it will crash at runtime. Please note that there is no way to check if there is nsNumberVar nil before using it!

 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 
+90
Oct. 14 '14 at 17:04
source share

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() } 
+7
Nov 05 '15 at 3:39
source share

Options is a fast specific function not available in obj-c. Optional class instances work because the optional nil parameter can be mapped to a null value, but the value types (int, float, etc.) are not reference types, so the variable of these types does not store the link, but the value itself.

I don’t know if there is a solution - a possible workaround creates optional properties that map the nil value to an unused data type value (for example, -1 when representing the index or 999999 for the 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 } 

This should show the _lat and _lon for obj-c.

Please note that I have never tried this, so please tell us if it works.

+3
Oct 14 '14 at 17:07
source share



All Articles