Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to access Swift 4 class from Objective-C: "Property not found on object of type"

Using the latest Xcode 9 beta, I'm seemingly completely unable to access properties on Swift classes. Even odder, I can access the class itself to instantiate it or whatever, but completely unable to access properties on it.

So if I have this Swift class:

import UIKit  class TestViewController: UIViewController {     var foobar = true } 

And I try to do this:

TestViewController *testViewController = [[TestViewController alloc] init]; // success testViewController.foobar; // error 

What exactly am I doing wrong? New project with Xcode 9.

like image 386
Doug Smith Avatar asked Aug 13 '17 03:08

Doug Smith


People also ask

How do I import a Swift file into 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 Objective-C in Swift?

You can use Objective-C and Swift files together in a single project, no matter which language the project used originally. This makes creating mixed-language app and framework targets as straightforward as creating an app or framework target written in a single language.


2 Answers

The rules for exposing Swift code to Objective-C have changed in Swift 4. Try this instead:

@objc var foobar = true 

As an optimization, @objc inference have been reduced in Swift 4. For instance, a property within an NSObject-derived class, such as your TestViewController, will no longer infer @objc by default (as it did in Swift 3).

Alternatively, you could also expose all members to Objective-C at once using @objcMembers:

@objcMembers class TestViewController: UIViewController {     ... } 

This new design is fully detailed in the corresponding Swift Evolution proposal.

like image 158
Paulo Mattos Avatar answered Sep 18 '22 07:09

Paulo Mattos


Swift 3.2/4.0 / XCode 9.1

You you set swift3.2 in project settings ( //:configuration = Debug SWIFT_VERSION = 3.2 )

you can use your code,(using the correct import file in objc, see below). If You set project to swift 4.0 ( //:configuration = Debug SWIFT_VERSION = 4.0 )

You must prepend @objc for every property.

So:

Swift 3.2:

// MyClass.swift  @objc class MyClass: NSObject{      var s1: String?     @objc var s2 : String? }   //  //  ViewController.m  import "MixingObjCAndSwift-Swift.h" #import "ViewController.h"  @interface ViewController ()  @end  @implementation ViewController  - (void)viewDidLoad {     [super viewDidLoad];             MyClass * mc = [MyClass new];     NSString * s1 = mc.s1;     NSString * s2 = mc.s2; } 

works.

Swift 4.0:

// MyClass.swift  @objc class MyClass: NSObject{      var s1: String?     @objc var s2 : String? }   .....   - (void)viewDidLoad {     [super viewDidLoad];             MyClass * mc = [MyClass new];     NSString * s1 = mc.s1;     NSString * s2 = mc.s2; } 

does NOT works: compiler fails:

/Users....ViewController.m:24:21: Property 's1' not found on object of type 'MyClass *'

as s1 is not prepended with @objc.

You must write:

@objc class MyClass: NSObject{      @objc var s1: String?     @objc var s2 : String? } 

(As a side-note: in C/C++/ObJC file, put always system/general *h files before your "local" class headers.)

Swift 4

just add @objcMembers before class @objcMembers class MyClassObject: NSObject { var s1: String! var s2: String!

} Swift evolutionenter link description here

like image 33
ingconti Avatar answered Sep 20 '22 07:09

ingconti