Dynamic Swift
众所周知,Swift 是一门静态语言,所有属性在编译期就已经确定下来了,对方法的派发是是静态完成的,类似于 C++ 的 vtable ,这样可以大幅提升 Swift 的性能,据统计,Swift 静态派发的的速度大约耗时为 1.1
纳秒,而 ObjC 的动态派发耗时为 4.9
纳秒,Swift 快大约 5 倍的时间,所以 Swift 性能比 ObjC 好,也就是因为 Swift 做了很多静态优化。
我们都知道,ObjC 跟 Swift 相反,ObjC 是动态语言,所有方法、属性都是动态派发和动态绑定的,这样给我们带来很多好处,比如我们可以全局的替换一个方法,或者在运行时替换示例的类型等等。在使用 ObjC 的时候,我们可以轻易的实现 AOP 编程。
我一度认为,Swift 真的就是一门静态语言,我可能是真的在内心深处不愿与去承认 Swift 的 ObjC 历史,因为我更愿意把 Swift 当做一门新语言来看待,在这样的背景下,我认为 Swift 是一门完完全全的静态语言,同时,我也认为为了使用 ObjC 运行时,我们需要在 Swift 里继承 NSObject。但是,事实发现这样的看法有问题,Swift 不是一门完完全全的静态语言,Swift 还可以做到动态派发,同时,Swift 可以不用继承 NSObject 而是而实现动态派发(这是苹果的一个彩蛋?查阅Swift文档之后发现,苹果早这么说过,但是我却选择忽略…)
ObjC Runtime 做了啥
我们都知道 ObjC Runtime 做了什么事情,他为我们提供了统一的数据结构,为我们描述了一个类、一个实例具有哪些实实在在的东西,而且,我们也很清楚的知道,ObjC 所有类都必须继承自 NSObject 。
更多关于 ObjC Runtime 的东西不在本文的讨论范畴。
Swift 有运行时吗?
答案是肯定的。但是,Swift 没有提供运行时访问的 API ,而且,Swift 本身是静态语言,他的运行时和动态性八竿子打不着。幸运的是,Swift 支持动态化,什么意思呢?Swift 有它自己的运行时,用来处理纯 Swift 语言的,做的工作肯定是很多静态优化的事情,所以,如果需要支持 Swift 动态化,我们需要使用 objc 的运行时机制,而且,Swift 本身就做了对 objc 运行时的兼容。
这是一个 Swift 类:
public class SwiftClass {
public var val: Int
public init(
_ val: Int)
{
self.val = val
}
public func echo(
_ val: Int) -> Int
{
return val
}
@objc
public dynamic func dynamicEcho(
_ val: Int) -> Int
{
return val
}
}
func objc_classes(of cls: AnyClass) -> [AnyClass] {
var clss: [AnyClass] = []
var cls: AnyClass? = cls
while let _cls = cls {
clss.append(_cls
cls = class_getSuperclass(_cls)
}
return clss
}
创建一个实例:
let classIns = SwiftClass(110)
查看一下dynamicIns
的类型:
print(objc_classes(of: object_getClass(classIns)!))
// [__lldb