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.
使用最新的Xcode 9 beta,我似乎完全无法访问Swift类上的属性。即使是odder,我也可以访问类本身来实例化它,但是完全不能访问它上的属性。
So if I have this Swift class:
如果我有这个Swift类:
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.
我到底做错了什么?使用Xcode 9的新项目。
3 个解决方案
#1
43
The rules for exposing Swift code to Objective-C have changed in Swift 4. Try this instead:
将Swift代码公开给Objective-C的规则在Swift 4中发生了变化。试试这个:
@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).
作为一个优化,@objc推理在Swift 4中被减少。例如,nsobject派生类中的属性(比如TestViewController)在默认情况下不再推断@objc(就像在Swift 3中那样)。
Alternatively, you could also expose all members to Objective-C as well using @objcMembers
:
或者,也可以使用@objcMembers将所有成员公开给Objective-C:
@objcMembers class TestViewController: UIViewController {
...
}
The new design is fully detailed in the corresponding Swift Evolution proposal.
新设计在相应的快速进化方案中得到了充分的详细说明。
#2
5
Swift 3.2/4.0 / XCode 9.1
Swift 3.2/4.0 / XCode 9.1
You you set swift3.2 in project settings ( //:configuration = Debug SWIFT_VERSION = 3.2 )
在项目设置中设置swift3.2(/:配置= 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 )
您可以使用您的代码(使用objc中正确的导入文件,请参见下面)。如果将项目设置为swift 4.0 (/:configuration = Debug SWIFT_VERSION = 4.0)
You must prepend @objc for every property.
对于每个属性,都必须预先使用@objc。
So:
所以:
Swift 3.2:
斯威夫特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:
斯威夫特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 *'
/用户.... ViewController。m:24:21:在“MyClass *”类型的对象上没有找到属性“s1”
as s1 is not prepended with @objc.
因为s1不是用@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.)
(附带说明:在C/ c++ /ObJC文件中,始终在“本地”类头之前放置系统/通用*h文件。)
#3
0
- When you add a swift file in your Objective-C project, Xcode will prompt to add Objective-C bridging header file, so allow the header file to be created.
- 当您在Objective-C项目中添加一个swift文件时,Xcode将提示添加Objective-C桥接头文件,因此允许创建头文件。
- In your Objective-C implementation file where you want to access the TestViewController property foobar. Use the following import syntax and replace the ProjectName with your project.
- 在Objective-C实现文件中访问TestViewController属性foobar。使用以下导入语法,并将项目名替换为项目名。
#import "ProjectName-Swift.h"
#进口“ProjectName-Swift.h”
Objective-C implementation file:
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
For more details go through the Apple Documents
有关更多细节,请参阅苹果公司的文件
#1
43
The rules for exposing Swift code to Objective-C have changed in Swift 4. Try this instead:
将Swift代码公开给Objective-C的规则在Swift 4中发生了变化。试试这个:
@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).
作为一个优化,@objc推理在Swift 4中被减少。例如,nsobject派生类中的属性(比如TestViewController)在默认情况下不再推断@objc(就像在Swift 3中那样)。
Alternatively, you could also expose all members to Objective-C as well using @objcMembers
:
或者,也可以使用@objcMembers将所有成员公开给Objective-C:
@objcMembers class TestViewController: UIViewController {
...
}
The new design is fully detailed in the corresponding Swift Evolution proposal.
新设计在相应的快速进化方案中得到了充分的详细说明。
#2
5
Swift 3.2/4.0 / XCode 9.1
Swift 3.2/4.0 / XCode 9.1
You you set swift3.2 in project settings ( //:configuration = Debug SWIFT_VERSION = 3.2 )
在项目设置中设置swift3.2(/:配置= 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 )
您可以使用您的代码(使用objc中正确的导入文件,请参见下面)。如果将项目设置为swift 4.0 (/:configuration = Debug SWIFT_VERSION = 4.0)
You must prepend @objc for every property.
对于每个属性,都必须预先使用@objc。
So:
所以:
Swift 3.2:
斯威夫特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:
斯威夫特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 *'
/用户.... ViewController。m:24:21:在“MyClass *”类型的对象上没有找到属性“s1”
as s1 is not prepended with @objc.
因为s1不是用@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.)
(附带说明:在C/ c++ /ObJC文件中,始终在“本地”类头之前放置系统/通用*h文件。)
#3
0
- When you add a swift file in your Objective-C project, Xcode will prompt to add Objective-C bridging header file, so allow the header file to be created.
- 当您在Objective-C项目中添加一个swift文件时,Xcode将提示添加Objective-C桥接头文件,因此允许创建头文件。
- In your Objective-C implementation file where you want to access the TestViewController property foobar. Use the following import syntax and replace the ProjectName with your project.
- 在Objective-C实现文件中访问TestViewController属性foobar。使用以下导入语法,并将项目名替换为项目名。
#import "ProjectName-Swift.h"
#进口“ProjectName-Swift.h”
Objective-C implementation file:
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
For more details go through the Apple Documents
有关更多细节,请参阅苹果公司的文件