无法从 Objective-C 访问 Swift 4 class:"Property not found on object of type"
Unable to access Swift 4 class from Objective-C: "Property not found on object of type"
使用最新的 Xcode 9 beta,我似乎完全无法访问 Swift classes 上的属性。更奇怪的是,我可以访问 class 本身来实例化它或其他任何东西,但完全无法访问它的属性。
所以如果我有这个 Swift class:
import UIKit
class TestViewController: UIViewController {
var foobar = true
}
我尝试这样做:
TestViewController *testViewController = [[TestViewController alloc] init]; // success
testViewController.foobar; // error
我到底做错了什么? Xcode 9.
的新项目
将 Swift 代码公开给 Objective-C 的规则在 Swift 中已更改 4. 试试这个:
@objc var foobar = true
作为优化,@objc
推断在 Swift 4 中减少了。例如,属性 在 NSObject
派生的 class 中,例如你的 TestViewController
,默认情况下 no 将不再推断 @objc
(就像在 Swift 3 中所做的那样)。
或者,您也可以使用 @objcMembers
:
立即将 所有 成员暴露给 Objective-C
@objcMembers class TestViewController: UIViewController {
...
}
此新设计在 the corresponding Swift Evolution proposal 中有完整的详细说明。
- 当您在 Objective-C 项目中添加 swift 文件时,Xcode 将提示添加 Objective-C 桥接 header 文件,因此允许创建 header 文件。
- 在您要访问 TestViewController 的 Objective-C 实现文件中 属性 foobar。使用以下导入语法并将 ProjectName 替换为您的项目。
#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
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: 属性 's1' 未在 'MyClass *'[=14= 类型的 object 上找到]
因为 s1 没有前缀@objc。
你必须写:
@objc class MyClass: NSObject{
@objc var s1: String?
@objc var s2 : String?
}
(作为 side-note:在 C/C++/ObJC 文件中,始终将 system/general *h 文件放在 "local" class headers.)
Swift 4
只需在class之前添加@objcMembers
@objcMembers class MyClassObject: NSObject
{
var s1:字符串!
var s2: 字符串!
}
Swift进化enter link description here
我在swift 3.0
中也遇到过这个问题
class 声明就是这样
class ClassA {
//statements
}
以上 class 无法在 Objective C 代码中访问,也未在 -Swift.h
中注册
一旦我像这样从 NSObject 继承:
class ClassA : NSObject {
//statements
}
class 可在 Objective c 中访问并在 -Swift.h
中注册
当您不想避免从 NSobject 继承时,此解决方案很有用 class。
Xcode 10.2 | Swift 4
在 class 之前添加 @objcMembers
解决了我的问题。
@objcMembers class MyClass:NSObject {
var s1: String!
var s2: NSMutableArray!
}
至于Swift 5.1 发现"@objc"不够用,还要弄成public"@objc public":
@objc public class SomeClass: NSObject {
@objc public let amount: NSNumber
...
使用最新的 Xcode 9 beta,我似乎完全无法访问 Swift classes 上的属性。更奇怪的是,我可以访问 class 本身来实例化它或其他任何东西,但完全无法访问它的属性。
所以如果我有这个 Swift class:
import UIKit
class TestViewController: UIViewController {
var foobar = true
}
我尝试这样做:
TestViewController *testViewController = [[TestViewController alloc] init]; // success
testViewController.foobar; // error
我到底做错了什么? Xcode 9.
的新项目将 Swift 代码公开给 Objective-C 的规则在 Swift 中已更改 4. 试试这个:
@objc var foobar = true
作为优化,@objc
推断在 Swift 4 中减少了。例如,属性 在 NSObject
派生的 class 中,例如你的 TestViewController
,默认情况下 no 将不再推断 @objc
(就像在 Swift 3 中所做的那样)。
或者,您也可以使用 @objcMembers
:
@objcMembers class TestViewController: UIViewController {
...
}
此新设计在 the corresponding Swift Evolution proposal 中有完整的详细说明。
- 当您在 Objective-C 项目中添加 swift 文件时,Xcode 将提示添加 Objective-C 桥接 header 文件,因此允许创建 header 文件。
- 在您要访问 TestViewController 的 Objective-C 实现文件中 属性 foobar。使用以下导入语法并将 ProjectName 替换为您的项目。
#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
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: 属性 's1' 未在 'MyClass *'[=14= 类型的 object 上找到]
因为 s1 没有前缀@objc。
你必须写:
@objc class MyClass: NSObject{
@objc var s1: String?
@objc var s2 : String?
}
(作为 side-note:在 C/C++/ObJC 文件中,始终将 system/general *h 文件放在 "local" class headers.)
Swift 4
只需在class之前添加@objcMembers @objcMembers class MyClassObject: NSObject { var s1:字符串! var s2: 字符串!
} Swift进化enter link description here
我在swift 3.0
中也遇到过这个问题class 声明就是这样
class ClassA {
//statements
}
以上 class 无法在 Objective C 代码中访问,也未在 -Swift.h
中注册一旦我像这样从 NSObject 继承:
class ClassA : NSObject {
//statements
}
class 可在 Objective c 中访问并在 -Swift.h
中注册当您不想避免从 NSobject 继承时,此解决方案很有用 class。
Xcode 10.2 | Swift 4
在 class 之前添加 @objcMembers
解决了我的问题。
@objcMembers class MyClass:NSObject {
var s1: String!
var s2: NSMutableArray!
}
至于Swift 5.1 发现"@objc"不够用,还要弄成public"@objc public":
@objc public class SomeClass: NSObject {
@objc public let amount: NSNumber
...