CocoaPods 1.5 is amazing!

CocoaPods 1.5 在前一段时间 release 了,其中有一个对于使用了 Swift 的项目非常重要 feature,那就是支持了 Swift 的 Static Library。

这还要讲讲 Swift Static Library 的历史。在 Xcode 9 之前,并不支持 Swift Static Library;Xcode 9 之后支持了 Swift 的 Static Library,但是使用 Swift + CocoaPods 的项目并没有办法使用 Static Library,因为 CocoaPods 不支持。在 CocoaPods release 1.4 版本 的时候,终于支持了在 use_framework! 的情况下使用 Static Library,但是对于 Swift 和 Objective-C 混编的项目还是未能完美支持;终于在 1.5 版本,Swift 的项目能用上 Static Library 了!

为什么这件事情令人兴奋呢?这还得从 Dynamic Library 说起。Apple 官方推荐每个 App 使用 Dynamic Library 的数量是 6 个,这是有原因的。因为在 App 启动的时候,dyld 会load 这些动态库,这会造成启动时间的增加;而且动态库数量过多,还会在 iOS 9 的设备上造成 dyld 的 crash。所以使用 Static Library 应该是每个使用了 Swift + CocoaPods 的项目都期望的事情。

在 CocoaPods 还未支持这件事情的时候,可以使用 cocoapods-amimono 这个插件。它会把所有 Dynamic Library 的符号拷贝到最终程序的可执行文件中,解决上面出现的两个问题。

既然使用动态库有这样那样的问题,那在升级了 1.5 以后,全都使用静态库不就好了?事是这么回事,但使用静态库也不是完美的,因为你还可能会遇到这样的问题:两个 Framework 中如果定义了相同名字的 C 函数会发生什么?调用 category 方法会 crash 等等,不过都比较好解决,不像 Dynamic Library 那样有硬伤。

总体上来说,使用静态库还是比动态库有优势的。

然而要想在项目中使用这个 feature,需要在 podspec 显示指定 s.static_framework = true,对于集成 100 多个 pod 的项目来说,一个个改起来太麻烦了,也不现实。但是 CocoaPods 是 Ruby 写的呀,我们可以通过 patch CocoaPods 来实现在只写几行代码的情况下,把所有 pod 变成 Static Framework,

在 Podfile 的同级目录创建 patch_static_framework.rb

1
2
3
4
5
6
7
module Pod
class PodTarget
def static_framework?
return true
end
end
end

在 Podfile 的最上面,引入该文件,

1
require_relative 'patch_static_framework'

这样对于 PodTarget 的 patch 就会在 pod install 的时候生效,所以我们就不需要改每个 pod 的 podspec 就可以实现每个 pod 都是 static_framework 的效果了,enjoy~