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

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

使用最新的Xcode9测试版,我似乎完全无法访问Swift类上的属性。更奇怪的是,我可以访问类本身来实例化它或其他什么,但完全不能访问它的属性。

所以,如果我有这个快速班:

1
2
3
4
5
import UIKit

class TestViewController: UIViewController {
    var foobar = true
}

我试着这样做:

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

我到底做错了什么?Xcode 9的新项目。


在Swift 4中,将Swift代码公开给Objective-C的规则发生了变化。试试这个:

1
@objc var foobar = true

作为一种优化,Swift 4中减少了@objc推理。例如,NSObject派生类中的属性(如TestViewController)将不再默认推断@objc(就像swift 3中那样)。

或者,您也可以使用@objcMembers一次将所有成员暴露给objective-c:

1
2
3
@objcMembers class TestViewController: UIViewController {
    ...
}

新设计在相应的快速发展方案中有详细说明。


Swift 3.2/4.0/Xcode 9.1

在项目设置中设置swift3.2(//:configuration=debugSwift_版本=3.2)

您可以使用代码(在objc中使用正确的导入文件,请参见下文)。如果将Project设置为Swift 4.0(//:configuration=debugSwift_版本=4.0)

必须为每个属性预先准备@objc。

所以:

斯威夫特3.2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 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;
}

作品。

斯威夫特4:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 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;
}

不工作:编译器失败:

/用户….viewcontroller.m:24:21:在"myClass*类型的对象上找不到属性"s1"

因为s1没有用@objc进行预处理。

你必须写:

1
2
3
4
5
@objc class MyClass: NSObject{

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

(作为一个旁注:在C/C++/Objc文件中,总是将系统/一般*H文件放在您的"本地"类头上)。

斯威夫特4

只需在上课前添加@objcmembers@objcMembers类MyClassObject:nsObject{var S1:字符串!V2 S2:字符串!

}此处为Swift EvolutionCenter链接说明


  • 在Objective-C项目中添加Swift文件时,Xcode将提示添加Objective-C桥接头文件,以便创建头文件。
  • 在您的Objective-C实现文件中,您希望访问TestViewController属性foobar。使用以下导入语法并用项目替换项目名。
  • #import"ProjectName-Swift.h"

    目标C实施文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #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文档


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

    班级宣言是这样的

    1
    2
    3
    class ClassA {
    //statements
    }

    在目标C代码中无法访问上述类,也没有在-swift.h中注册。

    一旦我继承了这样的nsobject:

    1
    2
    3
    class ClassA : NSObject {
    //statements
    }

    课程可在目标C中访问,并在-swift.h注册。

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


    Xcode 10.2 Swift 4上课前加上@objcMembers解决了我的问题。

    1
    2
    3
    4
    @objcMembers class MyClass:NSObject {
       var s1: String!
       var s2: NSMutableArray!
    }