Swift Library Evolution

1,261 阅读2分钟

从 Swift 5 开始,库能够声明稳定的 ABI,允许库二进制文 件替换为更新版本,而无需重新编译客户端程序。

环境变量:BUILD_LIBRARY_FOR_DISTRIBUTION

image.png

App链接了1.0动态库生成App产物,当动态库更新到2.0时,只需要重新编译动态库,App不需要重新编译。

创建一个macos命令行项目,添加workspace,再创建一个framework添加到workspace,语言都选swift。 在framework创建一个swift文件,写上代码:

public struct Person {

    public init() {}

    public var num1 = 1

}

frameworktargetbuildsettings中搜索BUILD_LIBRARY_FOR_DISTRIBUTION,看到这个环境变量默认值是NO

main文件中写入下面代码:

import Framework

print(Person().num1)

两个project没有添加任何关联依赖,先选择framework进行编译,然后再运行App,可以看到打印1

image.png

这时候把Person代码进行修改:

import Foundation

public struct Person {
    public init() {}
    public var num2 = 2
    public var num1 = 1
}

再编译framework,然后选择App scheme,选择Project -> Perform Action -> Run Without Building,可以看到打印结果变成了2

image.png

这是因为swift是一门静态语言,在编译的时候就确定了你动态库里面的存放方式,在调用的时候,识别的是你结构体里面的第一个属性,所以打印出来变成了2。如果把num2改成字符串,打印出来就是一个乱码数字。

swift在5.0以后,不管你哪个版本编译framework,只要你开启BUILD_LIBRARY_FOR_DISTRIBUTION,其他的就不用管了。只要替换现有库的位置即可。 把BUILD_LIBRARY_FOR_DISTRIBUTION修改为YES后,第一次一定要把Appframework编译一下,它才能确定哪些是需要运行时才确定的类型。把类型推到运行时又会导致运行速度变慢,swift提供了关键字@frozen,可以把你的库里面不想推到运行时的东西给冻住,冻住之后就不能像刚才那样推到运行时决定了。