无法从Objective-C访问Swift 4类:“在类型对象上找不到属性”

时间:2017-08-13 03:01:19

标签: ios objective-c swift xcode swift4

使用最新的Xcode 9 beta,我似乎完全无法访问Swift类的属性。甚至更奇怪,我可以访问类本身来实例化它或其他任何东西,但完全无法访问它上面的属性。

所以如果我有这个Swift类:

import UIKit

class TestViewController: UIViewController {
    var foobar = true
}

我尝试这样做:

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

我究竟做错了什么?使用Xcode 9的新项目。

6 个答案:

答案 0 :(得分:108)

将Swift代码暴露给Objective-C的规则在Swift 4中已经改变。试试这个:

@objc var foobar = true

作为优化,在Swift 4中减少了@objc推理。例如,NSObject派生类中的属性(例如TestViewController)将默认情况下推断@objc更长(就像在Swift 3中一样)。

或者,您也可以使用@objcMembers一次将所有成员公开给Objective-C:

@objcMembers class TestViewController: UIViewController {
    ...
}

新设计在the corresponding Swift Evolution proposal中详细说明。

答案 1 :(得分:9)

Swift 3.2 / 4.0 / XCode 9.1

您在项目设置中设置了swift3.2( //:configuration = Debug SWIFT_VERSION = 3.2

你可以使用你的代码,(在objc中使用正确的导入文件,见下文)。 如果将项目设置为swift 4.0( //:configuration = Debug SWIFT_VERSION = 4.0

您必须为每个属性添加@objc。

所以:

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;
}

作品。

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;
}

不起作用:编译器失败:

/ Users .... ViewController.m:24:21:在'MyClass *'类型的对象上找不到属性'1'

因为s1没有附加@objc。

你必须写:

@objc class MyClass: NSObject{

    @objc var s1: String?
    @objc var s2 : String?
}

(作为旁注:在C / C ++ / ObJC文件中,将“system”/ general * h文件放在“本地”类标题之前。)

Swift 4

在上课前添加@objcMembers @objcMembers 类MyClassObject:NSObject {     var s1:String!     var s2:String!

} 迅速进化enter link description here

答案 2 :(得分:2)

对于Swift 5.1,我发现“ @objc”是不够的,但是将其公开为“ @objc public”:

@objc public class SomeClass: NSObject {
    @objc public let amount: NSNumber
...

答案 3 :(得分:1)

  1. 在Objective-C项目中添加swift文件时,Xcode会提示添加 Objective-C桥接头文件,因此允许创建头文件。
  2. 在Objective-C实现文件中,您要访问TestViewController属性 foobar 。使用以下导入语法并将ProjectName替换为您的项目。
  3.   

    #import“ProjectName-Swift.h”

    Objective-C实施文件:

    #import "ViewController.h"
    #import "ProjectName-Swift.h"
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    
        TestViewController *testViewController = [[TestViewController alloc] init]; // success
        BOOL prop = testViewController.foobar;
        NSLog(@"Property: %d", prop);
    }
    
    @end
    

    有关详细信息,请查看Apple Documents

答案 4 :(得分:0)

我在Swift 3.0中也遇到了这个问题

类声明就是这样

class ClassA {
//statements
}

以上类无法在Objective C代码中访问,并且也未在-Swift.h中注册

一旦我像这样从NSObject继承:

class ClassA : NSObject {
//statements
} 

该类可在目标c中访问,并已在-Swift.h中注册

当您不想避免从NSobject类继承时,此解决方案很有用。

答案 5 :(得分:-1)

Xcode 10.2 |斯威夫特4 在上课前添加@objcMembers解决了我的问题。

@objcMembers class MyClass:NSObject {
   var s1: String!
   var s2: NSMutableArray!
}