CocoaPods组件化——OC/Swift动静态库混用

Published 2025-03-24 21:06 1749 words 9 min read

前端项目通过bridge获取客户端资源,客户端直接返回response对象常用代码模板1——基础算法常用代码模板2——数据结构统计iOS工程代码行数高数概念、公式、定理Objective-C 语法 3Objective-C 语法 2Objective-C 语法 1UIViewController 的生命周期UITableview调用reload方法时抖动问题UILabel中文带行间距的处理,限制行数,计算高度等UIButton扩大点击范围以及关于响应者链条的思考UIApplicationSwiftUI基本控件iPhone6 Plus上面神秘的缝隙iPhone 刘海机型UI适配(X、Xs、Xs Max、Xr)iOS:如何在UITableView调用reloadData刷新结束后再同步执行后续操作iOS 截取整个 scrollview 图片iOS 关于 UITextField 的字数限制Objective-C 中禁止调用指定的方法objc源码分析-runtime-classObjective-C Type EncodingsObjective-C:为什么分类中不能直接添加属性OC优缺点以及常见bugruntime——运行时简单使用当对象接收到不能处理的消息时调用的方法浅谈iOS中的weak为 UIControl 实现线程安全的 Block 事件扩展:原理与实践OC单例宏iOS常用数据类型转换OC中nil 、NULL、 Nil 、NSNull的区别Description方法和NSLog函数Block in Objective-CiOS自动化埋点的实现iOS平台编译Ogre游戏引擎库iOS:特殊符号大全iOS 网络小结iOS 沙盒与 BundleiOS 框架学习-AsyncSocketNSString的各种处理Swift Module 如何被全局引用CocoaPods组件化——OC/Swift动静态库混用COCOAPODS技巧-创建私有仓库关于NSNotificationCenter数据结构与算法解析习题2.23数据结构与算法解析习题2.19数据结构与算法解析习题2.16数据结构与算法解析习题2.14数据结构与算法解析习题2.13数据结构与算法解析习题2.12数据结构与算法解析习题2.11:二分查找数据结构与算法解析习题2.10:霍纳法则(Horner's rule)数据结构与算法解析习题2.7数据结构与算法解析习题1.3数据结构与算法解析习题1.2数据结构与算法解析习题1.1LeetCode 486 Predict the Winner(预测赢家)LeetCode 398 随机数索引LeetCode 106 Construct Binary Tree from Inorder and Postorder Traversal(由中序和后序遍历建立二叉树)LeetCode 70 爬楼梯(青蛙跳台阶)LeetCode 8 String to Integer (atoi)LeetCode 6 ZigZag Conversion(Z字转换)LeetCode 5 Longest Palindromic Substring(最长回文字串)iOS脚本打包 ipa(.app转.ipa)《什么是数学 》习题 第一章 补充《什么是数学 》习题 第一章 2 数系的无限性 数学归纳法《什么是数学 》习题 第一章 1 整数的计算Vue 的一些指令和缩写
This post is not yet available in English. Showing the original.
缘起 一个swift库,charts。 项目本身是通过 cocoapods 进行组件化管理的。 在没有集成 charts 之前,一切都是那么的美好,天是晴的,雨是停的。 直到有一天,因为业务需要图表功能,经一番调研之后,选择了 charts 集成到工程之中。 然后噩梦就开始了。 直接集成跑项目会直接

缘起

一个swift库,charts

项目本身是通过 cocoapods 进行组件化管理的。

在没有集成 charts 之前,一切都是那么的美好,天是晴的,雨是停的。

直到有一天,因为业务需要图表功能,经一番调研之后,选择了 charts 集成到工程之中。

然后噩梦就开始了。

直接集成跑项目会直接报上百个错,因为 charts 是用swift写的,错误简要如下:

Undefined symbols for architecture x86_64:
  "protocol witness table for Swift.Double : Swift.CVarArg in Swift", referenced from:
      static Charts.XFChartString.format2f(number: Swift.Double) -> Swift.String in libCharts.a(XFChartUtils.o)
  "base conformance descriptor for Swift.Comparable: Swift.Equatable", referenced from:
      protocol conformance descriptor for Charts.(LineAlt in _35CAD2F96B83BFC8E7052E13186FFBAD) : Swift.Comparable in Charts in libCharts.a(DataApproximator+N.o)
  "method descriptor for static Swift.Comparable.< infix(A, A) -> Swift.Bool", referenced from:
      protocol conformance descriptor for Charts.(LineAlt in _35CAD2F96B83BFC8E7052E13186FFBAD) : Swift.Comparable in Charts in libCharts.a(DataApproximator+N.o)

当时没想太多(这就是过于依赖搜索了,连分析都没直接去搜),搜的如何的oc项目通过 pod 集成swift代码。

大概翻了几篇的意思是swift只能动态库打包,需要 pod 管理的库改成动态库,其实这都是老黄历了,都是 pod1.5 之前的方案,不过我当时还是无脑跟着这么做了。

其实在这时候里胜利只差一步,结果绕了一个大弯子。如果不想看我废话这么多的,可以直接转到结局去看。

use_frameworks!

Podfile中加入 use_frameworks!,就可以让 pod 管理的库都改成动态库。

加上之后,重新 pod install 一下。

然后项目一跑,果然不报错了,哎呦,牛逼,这就解决了。

心里美滋滋的,现在回头来看,还是太年轻了,直接把库都弄成动态库,后面还有成吨的依赖问题在等着我。。

就如下面的标题: 动静态库 pod 内部依赖静态lib,静态framewor,动态framework,都是坑!

动态库 Pod 中嵌入静态 lib

先说一下最先遇到的就是动态库 Pod 中嵌入静态lib。

vendored_library属性对应依赖的.a,然后依赖系统库在library,frameworks里加上。

最后就是.h,如果你不想暴露的话public_header_files里加完就不用管了,如果想要暴露给别人调用,只能source_files里再加一遍.h。

不想在source_files里再写一遍的也可以建个.h引用一遍所有.a的头文件,最后source_files写你自己的.h,但这只是保证我到处可以通过引用自己的头文件实现方法调用,并不能单个引用对应.a的头文件。

动态库 Pod 嵌入静态 Framework

对静态的Framework封装的时候可以说是最简单的了,vendored_frameworks加上去基本就万事大吉了,至于依赖啥系统库什么的跟上面一样。

动态库 Pod 嵌入动态 Framework

对于动态的Framework封装,是最恶心的,就算不用 pod 也是很麻烦的。

不用 pod 你要手动把这SDK拖到Embedded Binaries位置头文件才能引用,这个是苹果现在引用动态Framework的方法。

下面讲一下 pod 怎么搞,如果单纯framework做 pod,首先public_header_files要指定xxx.framework/Headers/{.h}不然头文件找不到。

其次source_files里看具体编译情况决定加不加xxx.framework/Headers/{.h},然后就是比较普通的地方vendored_frameworks指定好就完事了。

source_files这个加了的时候还有一个前提就是Framework内引用全是""不能<>,所以大部分情况source_files不加。

另一种混合使用感觉这才是最常见的。

这时候不要指定Framework的public_header_files,写一个自己的头文件引用类,把想公开可以调用的写在在头文件引用类里如:#import <xxx.framework/xxx.h>,间接把xxx.h暴露出来。

静态库 Pod 资源文件的调用

静态库其实还好,跟 pod 有关的resourced都在相应的 pod库名.bundle 之中。 只需要用下面方法,就可以取出bundle,然海找相应的资源。

+ (NSBundle *)staticLibBundleWithModuleName:(NSString *)moduleName {
    
    NSURL *bundleURL = [[NSBundle mainBundle] URLForResource:moduleName withExtension:@"bundle"];
    NSBundle *bundle = [NSBundle bundleWithURL:bundleURL];
    return bundle;
}

动态库 Pod 资源文件的调用

每错,新坑出来了,动态 pod 中的静态framework,所依赖的资源图片找不到了。

打开ipa一看,路径全变了,pod 建动态库的时候的bundle都在相应的Framework里了。

大概路径就是:xxx.ipa/Frameworks/xxxpod.framework/xxxpod.bundle

真坑。。

所以获取bundle的方法改成下面的了。

+ (NSBundle *)dynamicLibBundleWithModuleName:(NSString *)moduleName {
    
    NSURL *bundleURL = [[NSBundle mainBundle] URLForResource:@"Frameworks" withExtension:nil];
    bundleURL = [bundleURL URLByAppendingPathComponent:moduleName];
    bundleURL = [bundleURL URLByAppendingPathExtension:@"framework"];
    bundleURL = [bundleURL URLByAppendingPathComponent:moduleName];
    bundleURL = [bundleURL URLByAppendingPathExtension:@"bundle"];
    
    NSBundle *bundle = [NSBundle bundleWithURL:bundleURL];
    return bundle;
}

关于动静之争

关于动态库和静态库的优劣网上一堆一堆的文章在说,这里就不废话了。

不过我个人倾向是用静态库的,事少,而且启动速度一些,说白了就是空间换时间。

安卓的art技术也是在空间换时间。

这年头空间哪有时间贵啊,手机容量再小,连这点都没有的那也不是我们的有效客户了。

结局

故事的答案是,我一开始以为swift不能打成静态库,所以导致的报错,其实并不是的。

当时报这个错是 Undefined symbols 错误,在后来把报错一搜,找到了 stackoverflow 上一个帖子

大概意思就是这个OC的项目不知道要编译Swift的代码才报错,只需要在主工程中,建一个空的swift文件并自动建一个bridge,然后就可以了。

没错,智慧就是这么简单,而我绕了好大的一个弯。

彩蛋1:Xcode9swift静态库的支持

一开始查的结果其实就是过时的,早在Xcode9,swift就支持打成静态库了,所以不用非要弄成动态库。

彩蛋2: pod1.5 use_modular_headers!

随着支持swift静态库,pod1.5也更新的对应的功能,如果swift的 pod 依赖于某个OC的 pod,需要为该OC版 pod 启用modular headers,所以多了 use_modular_headers!来全局开启,不过开启之后,之前一些不严谨的依赖,可能会报错,需要具体情况具体分析了,网上相关的文章也很多,就不在这里一一赘述了。而且我也不建议这种跨语言的交叉依赖,比如我的项目主要是OC,依赖的swift版 pod,就是纯swift写的。

再来点废话

虽然是过去式了,但是之前用 use_frameworks! 的时候,发现会给每一个 pod 创建一个 umbrella.h 文件,而这个文件里会有 pod 里所有的.h,当然这个是可以通过 podspec 中的属性控制的。如果 pod 里有 cpp 之类的文件,各种引用问题就很烦人了,还得一点一点改。

这是去年建新项目的时候一点心路历程,只是大概记个印象了,有的细节也不是很清楚了,等后面再遇到或者想起来了,再补充把。

引用:

https://stackoverflow.com/questions/52536380why-linker-link-static-libraries-with-errors-ios https://cloud.tencent.com/developer/news/252403 https://www.jianshu.com/p/10ed66dae403 https://blog.csdn.net/ios8988/article/details/84111011 https://www.jianshu.com/p/544df88b6a1e https://www.jianshu.com/p/be9c848d050f https://www.jianshu.com/p/4be1ef1dc3ff https://www.jianshu.com/p/dfe9a1e1db7f https://www.jianshu.com/p/913df8cc1f18 https://www.jianshu.com/p/35db14a4931c https://zhuanlan.zhihu.com/p/50571342

© 2024 - 2026 cos @cosine
Powered by theme astro-koharu · Inspired by Shoka