Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot access property on Swift type from Objective-C

I am trying to access a Swift class's Double? property from Objective-C.

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

In another view controller, I am trying to access lat like following:

#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 */ } 

and I am getting

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

Why can't I access this property? What am I missing?

like image 895
tranvutuan Avatar asked Oct 14 '14 16:10

tranvutuan


People also ask

How do I access Swift in Objective-C?

Import Swift code into Objective-C within the same framework: Under Build Settings, in Packaging, make sure the Defines Module setting for that framework target is set to Yes. Import the Swift code from that framework target into any Objective-C .

Can I use Swift library in Objective-C?

The Swift library cannot be directly called from Objective-C, since it is missing the required annotations in the code, and in many cases, modules do not inherit from NSObject, rather they use the native Swift data types.

Does SwiftUI work Objective-C?

You can use it in any way you would use a UIViewController. Takeaway: By depending on UIHostingController and the interoperability of Swift and Objective-C programming languages, you can use SwiftUI framework from within your Objective-C legacy code.

What is Property OBJC?

The goal of the @property directive is to configure how an object can be exposed. If you intend to use a variable inside the class and do not need to expose it to outside classes, then you do not need to define a property for it. Properties are basically the accessor methods.


1 Answers

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, 2  optTest.nsNumberOpt = nil; optTest.nsNumberVar = nil; [optTest badIdea]; // prints nil, then crashes with an EXC_BAD_ACCESS exception 
like image 143
Nate Cook Avatar answered Oct 06 '22 15:10

Nate Cook