Swift和Objective-C的共同使用

1.在 Swift 中使用 Objective-C 代码

这种情况下的做法很简单,只需要在项目中添加名为 {product-module-name}-Bridging-Header.htarget名称-Bridging-Header.h 文件,并在这个文件中添加你想要引用的头文件即可。为求方便, Xcode 还会在向项目中第一次添加 Objective-C 文件时候提示是否需要自动添加这个文件。

2.在 Objective-C 中使用 Swift 代码

如果所使用的 Swift 代码来自于外部框架(Framework),这时只需要使用 @import 导入框架即可。
如果只想使用某一个文件中的代码,这时可以直接导入自动生成的头文件 {product-module-name}-Swift.h 来完成。
但是这里存在的问题是,Obj-C 和 Swift 的底层实现是两套完全不同的机制,Cocoa 中的 Obj-C 对象是完全基于运行时的,是通过 KVC 和消息动态派发机制来运作的。但 Swift 为了提升程序的性能,没有特殊需求的情况下不再使用运行时来决定这些。而是在编译时将类的方法活着成员全部确定下来。运行时不需要再去进行查找等操作,直接根据内存地址来调用。

所以,当我们的 Objective-C 程序需要使用 Obj-C 的代码或者特性来调用纯 Swift 类的时候就会因为找不到对应的运行时信息而失败。所以在使用这些代码之前需要做一些简单的处理。即,为所有可能被 Obj-C 代码调用的地方添加 @objc 修饰。包括类,类的成员和方法。但是如果你写的 Swift class 继承自 NSObject 的话就不需要做这一步,因为 Swift 已经默认为所有继承自 NSObjectprivate 类和成员或方法 添加了 @objc 修饰,使用这些代码的时候,你就只需要简单的引入头文件就可以了。(也就是说 private 的类和成员并不会被自动添加,如果我们需要使用这些内容的动态特性的话,就必须手动为其添加@objc修饰)。

需要说明的一点是,使用了 @objc 修饰的 Swift 代码并不意味着会变成动态派发,Swift 仍然可能会对其进行编译优化。所以不能将这些内容当作运行时特性的代码来使用,如果需要类似 Objective-C 的完全运行时特性的话,这时你需要添加 dynamic 修饰符。