Swift项目中使用Objective-C代码
- 创建
工程名-Bridging-Header.h
文件,在文件中导入要使用的OC头文件#import "MyClass.h"
- 配置
工程名-Bridging-Header.h
文件路径build setting
->Objective-C Bridging Header
->$(SRCROOT)/OCAndSwift/OCAndSwift-Bridging-Header.h
Objective-C项目中使用来自外部的Swift框架
- 在podFile文件中使用
use_frameworks!
- 在使用的文件中添加
@import MySwiftKit;
Objective-C项目中使用同一个项目中的Swift代码
- 系统自动为我们生成了头文件(需要我们的
Swift
类是NSObject
的直接或间接的子类,Swift 会默认自动为所有的非private
的类和成员加上@objc
, 注意 如果需要将private 的类和成员需要暴露给Objective-C
,需要我们手动添加@objc
修饰符),我们只要#import 项目名-Swift.h
(#import "OCAndSwift-Swift.h") - 当项目名中含有
-
时,-
会转为_
, 如工程名为Tips-OCAndSwift
时,生成的头文件是Tips_OCAndSwift-Swift.h
- 如果不是NSObject的子类的话,需要将暴露给Objective-C的任何地方(类,属性和方法等)的声明前加上
@objc
修饰词。
Objective-C和Swift在底层使用的是两套完全不同的机制,Cocoa中的Objective-C对象是基于运行时的,它从骨子里遵循了KVC (Key-Value Coding,通过类似字典的方式存储对象信息)以及动态派发(Dynamic Dispatch,在运行调用时再决定实际调用的具体实现)。而Swift 为了追求性能,如果没有特殊需要的话,是不会在运行时再来决定这些的。也就是说,Swift类型的成员或者方法在编译时就已经决定,而运行时便不再需要经过一次查找,而可以 直接使用。
显而易见,这带来的问题是如果我们要使用Objective-C的代码或者特性来调用纯Swift的类型时候,我们会因为找不到所需要的这些运行时信息,而导致失败。解决起来也很简单,在Swift类型文件中,我们可以将需要暴露给Objective-C使用的任何地方(包括类,属性和方法等)的声明前面加上 @objc
修饰符。注意这个步骤只需要对那些不是继承自 NSObject
的类型进行,如果你用Swift写的class是继承自 NSObject
的话,Swift会默认自动为所有的非private的类和成员加上 @objc
。这就是说,对一个 NSObject
的子类,你只需要导入相应的头文件就可以在Objective-C里使用这个类了。
@objc
修饰符的另一个作用是为Objective-C侧重新声明方法或者变量的名字。虽然绝大部分时候自动转换的方法名已经足够好用(比如会将Swift中类似的方法转换成这样),但是有时候我们还是期望Objective-C里使用和Swift中不一样的方法名或者类的名字,比如Swift里这样的一个类:
class 我的类 {
func 打招呼(名字: String) {
print("哈喽,\(名字)")
}
}
我的类().打招呼(名字: "小明")
Objective-C 是无法使用中文来进行调用的,因此我们必须使用将其转为ASCII才能在Objective-C里访问:
@objc(MyClass)
class 我的类 {
@objc(greeting:)
func 打招呼(名字: String) {
print("哈喽,\(名字)")
}
}
这样,我们在Objective-C里就能调用 [[MyClass new] greeting: @"XiaoMing"]
这样的代码了(虽然比起原来一点都不好玩了)。另外,即使是 NSObject
的子类,Swift也不会在被标记为 private
的方法或成员上自动加 @objc
,以保证尽量不使用 动态派发 来提高代码执行效率。如果我们确定使用这些内容的动态特性的话,我们需要手动给它们加上 @objc
修饰。
但是需要注意的是,添加修饰符并不意味着这个方法或者属性会变成动态派发,Swift依然可能会将其优化为静态调用。如果你需要和Objective-C里动态调用时相同的运行时特性的话,你需要使用的修饰符是 dynamic
。一般情况下在做app开发时应该用不上,但是在施展一些像动态替换方法或者运行时再决定实现这样的"黑魔法"的时候,我们就需要用到 dynamic
修饰符了。
关于Swift和Objective-C混用的一个好消息是,随着Swift的发展,Apple正在努力改善SDK。 在Objective-C中添加的 nonnull
和 nullable
,以及泛型的数组和字典等,其实上都是为了使SDK更加适合用Swift来使用所做的努力,我们还是很有希望在不久的未来能够摆脱掉这些妥协和束缚的。