AI 年度盘点与2025发展趋势展望,50+案例解析亮相AICon 了解详情
写点什么

组件化:动态库实战续

  • 2019-09-20
  • 本文字数:3178 字

    阅读完需:约 10 分钟

组件化:动态库实战续

上篇文章中我们已经完美的解决了使用 swift 第三方库 ,使用混编的组件,使用 use_framework!,但是会带来别的问题。果然是生命不息,折腾不止啊。

不建议组件化项目中用 Swift 写业务

Q: C++/C 静态库依赖问题 A:回想下我们在做 C 或者 C++ 开发的时候。如果一个静态库依赖另外一个静态库( A 依赖 B )。那么被依赖库 B 升级的时候 A 用重新编译吗?不一定,如果是一些方法的新增,维护,不一定会让 A 重复编译;但是如果修改了 B 里面的数据结构,A 里面又用到了这些数据结构,那么很大可能性我们就要重新编译 A 了。Q:Objective-C 静态库依赖问题 A:回想下我们在 iOS 中出现上述的依赖问题,貌似也没有见到要重新编译 A 的情景。主要是 Objc2.0 引入了 non-fragile 特性,同时 OC 是严重依赖于 Runtime 的,只要接口兼容,就算你修改了 B 中的数据结构,一般也是不需要重新编译 A 的。如果你不明白 non-fragile 请看文后的参考链接 Q: Swift 中库依赖问题 A:由于 Swift 不和 OC 一样,所有的 OC 方法都是通过 Runtime 动态调度的。Swift 对于方法是存在静态调度和动态调度 2 种的。所以 Swift 的库依赖极易引起二进制兼容性问题。更多关于 Swift 库二进制接口 (ABI) 兼容性问题,请参考文后链接。


Q: 为什么不建议在组件化的项目中使用 Swift 或者和 OC 混编来写业务?A: 在组件化初期的时候,我们能做到的一般是基础库抽离,业务组件分离这些。但是一般来说我们这时候的壳工程,接入这些分离的组件的时候都是使用源码接入,这时候问题暂时显现不出来。当我们的组件化的脚步越走越远的时候,我们出于多方面的考虑可能有以下需求。


**1. 开发时重复编译是痛点。**我们可能更希望提供的是二进制版本,节省下大量的编译耗时;


**2. 我们可能要做权限管理。**有时候一个公司业务和人员规模都非常庞大。我们基础库设计到跨业务,跨 APP 使用。我们希望不同团队有不同基础组件的读写权限。那么我们更可能偏向提供二进制库加文档的形式。


综上:由于使用 Swift 开发 ABI 不兼容问题更易出现。在组件化的项目中,不建议使用 Swift 或者混编。


Q:动态库过多启动较慢问题 A: 上面说到的问题(麻烦)其实是带给开发者的麻烦,但是动态库多了会给用户带来麻烦(APP 启动耗时)。用了混编的项目我们在 Podfile 里面势必要写 use_framework!,上篇文章中我们也说到用了这个指令。


CocoaPods 会帮我们把所有的库全部编译为动态库。这些动态库是在 APP 启动时做去加载的。我们在组件化的时候,自己的业务组件马上接近上百个。可以预想到以后随着组件化的越来越深入,这些库会越来越多。这个时间可能会达到 1s 的量级。对于用户这是不可接受的。关于动态库过多导致的启动慢的问题请参考文后的参考链接。

结合公司目前的情况的解决方案

我们公司目前的情况: Swift 第三方库个别,混编组件个别。既然都是个别的,我们总不能因为这些个别的特殊 case 让 APP 原本的 1 个二进制文件变成 1 个二进制文件+ 上百个动态库 framework 。这肯定是不合理的。解决办法


1. 不使用 Swift,包括第三方库和混编组件


2. 部分组件(含有 Swift )动态库化,其他部分仍旧整合进 app 的二进制中


首先来看办法


直观感觉是不合适。首先很多公司的项目在做组件化的时候项目已经达到一定程度(没有一定规模也没必要做组件化),这就意味着大部分 APP 是有历史包袱的。首先重写这些已有的组件或者功能肯定是有风险的,在公司业务多。用户量大的情况下,影响面会更大,虽然这样是一劳永逸的,但是同时风险是更大的。我们在做组件化的工作中,改善大家开发的痛点,提高开发效率才是主要目标。至于重构甚至重写则是业务方的重心。第二种办法就是做到部分组件动态库化。我们来回忆下静态库的特点。静态库和主工程链接的时候会把库里面的代码复制到可执行文件中。对于这部分符号在 APP 启动时会省去 load,rebase,binding 的时间。那么在 iOS 平台中嵌入式动态库的特点是不把库里面的代码复制到可执行文件中,而是单独复制到 APP 里面的 frameworks 路径下。通常来说动态库节省内存,是因为内存中只有一份库代码。但是在 iOS 平台上由于苹果公司的限制我们又做不到减少内存。静态库的缺点是会让 APP 安装包增大。那么我们自己做的嵌入式动态库也会有这个问题。并且还会导致 APP 启动变慢。那岂不是优点变成了缺点~~.以上讨论只在正常项目且上架到 APP Store 渠道,越狱开发和企业版证书发布不做讨论

组件化部分动态库实战

上篇文章中我们知道只要你的组件库中使用到了 Swift 。以源码的方式提供给壳工程使用的时候一定要加上 use_framework!, 那么就变成前文说到了上百个动态库了。那么我们如果不以源码的形式引入呢。对于这些含有 Swift 的下层组件是无依赖的。我们直接将其编译为动态库提供二进制。那么我们在主工程使用的时候就不需要加入


use_framework!.


#use_frameworks!

source 'https://github.com/ValiantCat/LJWXSDK'
source 'https://github.com/CocoaPods/Specs.git' #官方仓库的地址
target 'LJA_Example' do
pod 'LJA', :path => '../'
pod 'LJB', :path => '../'
pod 'LJCharts'
end
复制代码


那么我们拉下来的项目结构是这样的



但是我们运行发现 libswiftCore.dylib 无法加载。



出现这个情况是因为 Xcode 不知道你使用了 Swift 代码,所以并没有把 Swift 的运行时环境(也就是 swif t 运行的动态库)复制进 APP 目录。那么解决办法其实很简单。我们在壳工程新建一个 swift 空文件即可。以下是主工程是否有 swift 文件 APP 目录下动态库的对比。




到这里其实这篇文章就好了。剩下的其他组件就继续使用静态库即可。我们可以愉快的玩耍了。

未解决的问题

前面说的问题文中已经解决。但是我觉得有一点不爽。那就是我还需要手动得在壳工程添加空的 Swift 文件。那么我们能不能这一步也自动化呢。首先我建了一个空工程,往里面添加了一个空的 Swift 文件。然后 diff 了一下两次的 project 文件。以下是 diff 结果样的



我们知道 podspec 和 Podfil e 其实都是 ruby 代码。Xcode 如何知道我们是否有 swift 其实也是通过工程的配置来知晓的。那么我们其实可以在 Podfile 去写 ruby 代码修改工程文件。这样的话使用方就不需要疑惑为什么要加个空的 swift 文件了。以下是代码


# Pod设置 =================================
def update_config (config) config.build_settings['CLANG_ENABLE_MODULES']= 'YES' config.build_settings['SWIFT_VERSION']= '3.0' #config.target_attributes["LastSwiftMigration"] = "0830" ifconfig.name =="Debug" then config.build_settings['SWIFT_OPTIMIZATION_LEVEL']= '-Onone'
end# elsif config.name == "Release"then# config.build_settings['CLANG_ENABLE_MODULES'] = 'YES'# config.build_settings['SWIFT_VERSION'] ='3.0'# endendpost_install do |installer| projects= [ "SwiftConfig" ] projects.eachdo |proj| path= "%s.xcodeproj"% [proj] single_project= Xcodeproj::Project.open(path) single_project.targets.eachdo |target| target.build_configurations.eachdo |config| printpath, ' ', target.name, ' ', config.name puts"" update_configconfig end target.attributes.methods.eachdo |xx| putsxx end end single_project.save endend
复制代码


不过加入这段代码后发现。我虽然确实成功的修改了工程文件。但是发现 Xcode 依旧没有把 Swift 运行时的库给我复制进 APP 里面。所以这还算是一个不完美的地方。后续有结果的话更新此文。


本文转载自公众号贝壳产品技术(ID:gh_9afeb423f390)。


原文链接:


https://mp.weixin.qq.com/s/6xDlSnxug51g3ThYoM-gcA


2019-09-20 09:571303

评论 1 条评论

发布
暂无评论
发现更多内容

Hypium框架使能ArkTS应用高效测试

HarmonyOS开发者

HarmonyOS

2022 IoTDB Summit:IoTDB PMC 田原《大规模并行处理与边缘计算在 Apache IoTDB 中的实践》

Apache IoTDB

数据库 IoTDB

字字珠玑!GitHub爆赞的网络协议手册,被华为大佬指定内部必学?

做梦都在改BUG

Java 计算机网络 网络协议

零基础如何学习Web 安全,如何让普通人快速入门网络安全?

网络安全学海

黑客 网络安全 信息安全 渗透测试 WEB安全

JDK 环境配置

流火

Java centos jdk window

新必应(New Bing)申请出错终极方案

kcodez

微软 ChatGPT New Bing

人工智能+低代码,打通AI落地的最后“一公里”

明道云

高性能存储SIG月度动态:ANCK 5.10正式支持ublk、erofs容器镜像按需读时延优化60%

OpenAnolis小助手

操作系统 高性能存储 龙蜥社区 sig

LeetCode题解:2373. 矩阵中的局部最大值,遍历,详细注释

Lee Chen

JavaScript LeetCode

MongoDB写入数据策略

NineData

nosql mongodb Journaling 写入策略 读策略

Portraiture4中文免费ps滤镜磨皮插件

茶色酒

Portraiture3

一文彻底弄清楚分布式锁

做梦都在改BUG

Java 分布式锁

Clean Start与Session Expiry Interval - MQTT 5.0新特性

EMQ映云科技

物联网 IoT mqtt 客户端 企业号 3 月 PK 榜

2022 IoTDB Summit:IoTDB PMC 曹高飞《Apache IoTDB 秒级扩容能力与存算分离实践》

Apache IoTDB

数据库 IoTDB

ChatGPT Turbo API 18元/100万个单词

kcodez

openai ChatGPT

【我在京东做研发】揭秘支撑京东万人规模技术人员协作的行云DevOps平台

京东科技开发者

2022 IoTDB Summit:Apache IoTDB PMC 张金瑞《为物联网场景优化的时序数据库共识协议》

Apache IoTDB

大数据 IoTDB

在深圳龙岗,看见空间智能化的潮水涌动

脑极体

全屋智能

会声会影2023中文最新版消息

茶色酒

会声会影2023

SpringBoot+ThreadPoolTaskExecutor 批量插入百万级数据实测

做梦都在改BUG

Java Spring Boot 多线程 ThreadPoolTaskExecutor

赞不绝口!仅靠阿里P9分享的 Redis 工作手册,拿到60W年薪Offer

做梦都在改BUG

Java 数据库 redis 缓存 面试

开源如何推动云计算的发展与创新 | 雨林开源行

开源雨林

开源 kubenetes OpenStack

架构实战营模块1第3课 - 什么是面向复杂度架构设计

净意

图像的滤波与图像增强的Matlab实现

timerring

数字图像处理

再有人问你什么是分库分表,直接把这篇文章发给他

做梦都在改BUG

Java 分库分表

堪称神级!GitHub上标星157K的Java教程,全程干货,只讲重点

做梦都在改BUG

Java

老铁们看过来!2023首场昇腾AI开发者创享日来到“东北黑土地”沈阳

科技热闻

ClickHouse 与 Amazon S3 结合?一起来探索其中奥秘

亚马逊云科技 (Amazon Web Services)

在文心一言出生地,百度悄悄燃烧AI小宇宙

白洞计划

百度 文心一言

FL Studio2023免费中文版数字音频工作站软件

茶色酒

FL Studio2023

得物供应链复杂业务实时数仓建设之路

小小怪下士

Java 程序员 后端

组件化:动态库实战续_文化 & 方法_姜沂_InfoQ精选文章