Swift Framework 弱链接
Swift Framework 弱链接
对 Framework 进行弱链接,即不保证在运行时能找到链接的符号,这通常适用于一个 Framework 对另一个 Framework 进行弱链接,以减小二进制大小以及提供模块化设计。
下面以 ToasterKit
和 ToasterKitCore
为例。ToasterKitCore
提供基础功能,ToasterKit
依赖 ToasterKitCore
,但自身不嵌入 ToasterKitCore
,而是对其进行弱链接。
创建 ToasterKitCore
首先在 Xcode 中创建一个 Framework
,并命名为 ToasterKitCore
,其中提供下面的简单代码:
1 | public enum Toast { |
对于 ToasterKitCore
无需更多操作,弱链接的设置在 ToasterKit
中进行。
设置 ToasterKit
以相同的方式创建 ToasterKit
,并将 ToasterKitCore
的 xcodeproj
文件嵌套到 ToasterKit
项目结构下。(这里主要是为了让 ToasterKit
能找到 ToasterKitCore
的符号,没有 xcodeproj
的话添加编译后的 .framework
文件也可以。)
在 Xcode 的项目设置中,选中 ToasterKit
Target,在 Frameworks and Libraries 下添加 ToasterKitCore.framework
并选择 Do Not Embed。然后转到 Build Phases 下,展开 Link Binary With Libraries,将 ToasterKitCore.framework
的 Status 改为 Optional。
通过这些设置,链接器在链接时就会对 ToasterKitCore
进行弱链接,不会在编译时要求 ToasterKit
的二进制文件中包含这些符号。
在代码中使用
在 Swift 中,通过 @_weakLinked
属性配合 import
来告知编译器导入的库是弱链接的:
1 | import ToasterKitCore |
随后可以同一般的 Framework 一样使用 ToasterKitCore
中的声明:
1 | var myToastStatus = Toast.perfect |
注意:如果在运行这行代码的时候找不到
ToasterKitCore.framework
,App 会以EXC_BAD_ACCESS(0x0)
崩溃。
若要更安全地使用弱引用的符号,可以在使用其符号前添加判断逻辑:
1 | public struct AdvancedToast { |
ABI 兼容
如果把这两个 Framework 添加到同一个项目中,ToasterKit
既依赖 ToasterKitCore
,同时又是相对独立的。在 ToasterKitCore
需要更新时,只要没有破坏性更改,无需重新编译 ToasterKit
。
这里说的破坏性更改即破坏 ABI(Application Binary Interface) 兼容性的更改。简单来说,添加内容一般不会破坏 ABI 兼容性,而对已有的声明进行重命名或删除等操作,就会破坏 ABI 兼容性。
使用 @available
标记可以在提醒调用方此声明已弃用的同时保留 ABI 兼容性:
1 | @available(*, deprecated, renamed: "NewToast", message: "'Toast' has been deprecated, use 'NewToast' instead.") |