Swift调OC比较简单,之所以这么说,是因为Swift覆盖OC的大部分功能,即使有些没有覆盖,官方肯定也会给出解决方法。而OC相对于Swift而言,很多Swift特有的新功能OC是没有的,所以,OC可能在调用Swift的时候,会将Swift特有的功能引入OC,这个时候就会出错,因为,OC支持不了Swift的新功能。
OC调用Swift,需要先#import "工程名-swift.h"
1.如果Swift类没有继承自NSObject,那么OC不能调用,给类加上: NSObject
。系统会给继承自NSObject的类,自动加上@objc
修饰,除了private修饰的方法和属性。
2.不是继承自:NSObject
的类,需要手动在方法或属性前加上@objc
,Swift之后,即使是继承自:NSObject
的类,也需要显式添加@objc
才能访问。之前是默认添加的。
3.Swift中的枚举,OC中不能使用,OC中枚举实际都是Int型:
enum MethodType {
case POST
case GET
case DELETE
}
改成:
@objc enum MethodType: Int {
case POST
case GET
case DELETE
}
注意,要继承Int
,加上@objc
。
5.在Swift中是结构体类型,但是在OC中是基本数据类型,所以,如果在Swift只是表示一个简单的基本数据类型的话,OC可以转换,如果表示的是一个结构体才有的功能,那么OC无法转换。
class ViewController: UIViewController {
@objc var a: String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
}
这里的变量a可以转换,查看一下工程名-Swift.h
文件,的确生成了OC头文件:
SWIFT_CLASS("_TtC4TEST14ViewController")
@interface ViewController : UIViewController
@property (nonatomic, copy) NSString * _Nullable a;
- (void)viewDidLoad;
- (nonnull instancetype)initWithNibName:(NSString * _Nullable)nibNameOrNil bundle:(NSBundle * _Nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER;
@end
如果将这里的a类型改为Int
会怎么样:
class ViewController: UIViewController {
@objc var a: Int?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
}
会报错:Property cannot be marked @objc because its type cannot be represented in Objective-C
今天正在导致我发现这个问题的是下面的代码:
typealias TestClouse = (String,Int?) -> ()
class ViewController: UIViewController {
@objc var clouse: TestClouse?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
}
系统会报上面提到的错误,但是停在clouse
变量这行。道理还是一样的。
这里就是上面解释的,当Int
成为可选类型的时候,这里的Int
已经不光是表示一个简单的Int
类型了,而是带有明显的结构体属性,因为是可选,即表示,可能是nil
,而OC里的Int类型或者NSInteger都是基本数据类型,不能为nil
。
所以,要解决这个问题,只能在Swift中避免将OC中的基本数据类型设置为可选类型。
附上系统转换的OC头文件代码:
@interface ViewController : UIViewController
@property (nonatomic, copy) void (^ _Nullable clouse)(NSString * _Nonnull, NSInteger);
- (void)viewDidLoad;
- (nonnull instancetype)initWithNibName:(NSString * _Nullable)nibNameOrNil bundle:(NSBundle * _Nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER;
@end
6.OC不支持Swift中的泛型,虽然从Xcode7,OC就引入了泛型的支持,但是这个泛型,我们称作轻量级泛型,和Swift中的重量级泛型还是对不上,当然,硬是要去对接,苹果应该也能做,但毕竟不是同一个东西,强行对接反而不好。
参考Stack Overflow上的讨论
目前遇到这几个问题,后面有新问题再更新
参考资料:swift: @objc的使用