惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
The Register - Security
The Register - Security
Hugging Face - Blog
Hugging Face - Blog
博客园 - 聂微东
GbyAI
GbyAI
Recent Commits to openclaw:main
Recent Commits to openclaw:main
博客园_首页
D
Docker
S
Security @ Cisco Blogs
K
Kaspersky official blog
爱范儿
爱范儿
Simon Willison's Weblog
Simon Willison's Weblog
TaoSecurity Blog
TaoSecurity Blog
V
V2EX
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Troy Hunt's Blog
Cloudbric
Cloudbric
博客园 - 三生石上(FineUI控件)
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
The Hacker News
The Hacker News
美团技术团队
S
SegmentFault 最新的问题
L
Lohrmann on Cybersecurity
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
宝玉的分享
宝玉的分享
The Last Watchdog
The Last Watchdog
Y
Y Combinator Blog
M
MIT News - Artificial intelligence
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Martin Fowler
Martin Fowler
Google Online Security Blog
Google Online Security Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
C
Cybersecurity and Infrastructure Security Agency CISA
T
Tor Project blog
Vercel News
Vercel News
The Cloudflare Blog
G
Google Developers Blog
T
Threat Research - Cisco Blogs
AI
AI
Stack Overflow Blog
Stack Overflow Blog
I
InfoQ
Scott Helme
Scott Helme
S
Schneier on Security
大猫的无限游戏
大猫的无限游戏
The GitHub Blog
The GitHub Blog
S
Securelist
IT之家
IT之家
Microsoft Azure Blog
Microsoft Azure Blog

一个工匠

AI 发展临界点 - 快上车 流式响应(Chat):HTTP 响应体字节流的读取与解析 iPhone 截屏高效翻译 Flash Open Terminal iPhone 侧载安装 Xcode Symbolic Debug AI 指北 投资风险收益评估 Mac 快速修改系统快捷键 Git Record passkey How to pay Mac - Command Line Tools DNS 的 CNAME 是如何工作的 WebRTC 的一些解释 SSE 指南 1.1.1.1、WARP 和 MASQUE 移动端换端方案与场景还原 设备发现 分辨率 - 像素密度 - HiDPI Mac 字体 ESP32 trump - 川普 币圈 - 虚拟货币 【旅游】富士山 【旅游】sakura(樱花) 【旅游】千岛湖 我的 2023 【Swift】中文词语纠错 计算机字符编码与内存编码 - Unicode、UTF8、String 从汇编角度理解 “函数调用栈” 和 “有栈协程” 在 Xcode 中更好的使用 Swift 通过 Swift Package 制作二进制库 Arc 浏览器 - 意外的惊喜 【Swift 三方源码 1】SwiftShell 高效的命令行工具 Swift 脚本开发环境搭建 rime - 小鹤双拼 【旅游】沿海旅游 (威海、青岛) 好记性远远不如烂笔头 高级语言小记 又一年高考 Vision 未来已来 致敬耗子哥 Socket 与 ICMP 对互联网隐私的一些想法 网络代理是如何工作的 (致敬 Surge) 又十年 - 至三十而立 双拼 - 少有的高回报效率技能 Vim 技巧 我的 2022 三年疫情五味杂陈 - 下 老梗 - 浏览器按回车后发生了什么 三年疫情五味杂陈 生活推荐清单 Shell 和进程 有计划的努力 内卷 不确定性 数学可以保障逻辑自洽 这些年我的软件清单 决定做一些改变 函数调用栈之彻底理解 锁 - 共享数据安全指↑ 江苏女有感 碎碎念 - 2022 碎碎念 - 2021 打算记录一些碎碎念 多重性格就是逆天改命 从 Core Foundation 看更大世界 TCP 数据传输过程分析 iOS main 文件中的 @autoreleasepool 的真实用途 多线程的难点在哪里 Objective-C 和 Runtime 早起打卡计划 ing 打比方 IM 和 Socket 的关系及 Heart 的必要性 如果我的人生突然只剩下 8 小时... 胡说八道之雪粉 Array 和 LinkedList 的深刻认知 Swift struct (值类型) 与 class (引用类型) 区别及三种传参机制深刻关系和使用 逃离信用卡和花呗 Swift_let_var_struct_class 网聚人的力量 - 网易 绿皮火车 喝酒十之八九会误事 HKong 胡说八道之云服务 互联网网络传输协议理解坑点 CPU 的制作 我心里一直有一个念想 网络基础协议 为什么 32 位操作系统只能用 4G 内存空间 努力和天赋 洗牙 RAC-Api-Summer iOS 内存原理 Block 闭包简查记录 《白夜行》 谈谈事件驱动 老博新开 祭首
apple frameworks
海驴 · 2024-11-14 · via 一个工匠

动态库 & 静态库,若单独输出并接入主工程,逻辑倒很清晰。如果牵涉到多个 framework 不同类型并且相互依赖,会增加不少复杂度。
以下说明中,动态库使用 DFramework 表示,静态库使用 SFramework 表示。

1 framework

仅需要提供 1 个 framework,直接提供 DFramework 即可。DFramework 优先,必要的时候再提供 SFramework

n framework

因为代码结构分组,可能需要提供多个 framework:

  1. DFramework 优先,能不提供 SFramework 就不要提供
    • 有 n 个 DFramework 就提供 n 个。相互之间做好依赖文档,App 需要根据依赖文档 flat 平铺接入所有需要的 DFramework。
    • 如果 b DFramework 仅仅被 a DFramework 依赖,可以将 b 打入 a DFramework 的 frameworks文件夹中,通过 embed 实现。
      • 这样就可以不再文档中说明 b DFramework 的存在,对外界透明。
      • 这种方案,最终的 app 中 framework 不是 flat 平铺的,而是具有层级结构,如 :App - a DFramework - b DFramework
    • 如果 b DFramework 同时被 m DFramework 和 n DFramework 依赖,不能将 b 隐藏(打入 m 和 n 中)。
      • 否则,App 集成 m 和 n 的时候,b 会出现多份。如果 b 的版本不一样,将按照打包顺序只使用其中一个。
  1. 如果提供 SFramework,则将所有的 framework 做成依赖,输出一份 SFramework 即可。
    • 如果有按需接入的场景,按按照场景输出 n 个 SFramework。

依赖开源库

一般这种场景是因为开发 framework 的同时,又使用了开源的库。这个时候如何处理开源库是个问题(开源库一般都是 源码 提供的,不讨论 闭源包 提供方式,这个和上面的场景一致)。
由于 apple 的 Swift Package Manager 三方库管理的介入,一个 module 在最终的 app 中到底是 dymanic 还是 static,已经不可控了。SPM 会自行管理,不像 cocoapods 的时候我们可以自行控制。

如果是源码提供者,可以增加 dymanic / static 约束。但很多源码都不会提供这个选项,而是让 SPM 自行管理采用哪一个。

在这种场景下,开发的 framework 如果对开源库有依赖,就必须考虑是否【去开源】事宜了。
另外,除了自己使用开源库,App 主工程开发者,可能也需要使用同一个开源库,这时候还会出现【版本不一致问题】。
以下场景,假设有 T 开源代码需要使用:

不封装,让外界接入

framework 需要依赖 T

  • 如果不是强依赖,在 xcode 中使用 -weak_framework进行标记,这样业务也可以不接入,相当于默认不使用这个功能。
  • 如果是强依赖,并且在 文档 中说明业务需要接入 x 的具体版本范围。不接入无法编译或者 app 启动闪退。

封装,外界无感

第一步就是需要对 T 进行【模块隔离】,否则外界也接入 T 的时候,App 主工程和我们提供的 framework 同时有 T 代码,会有问题。
虽然 xcode 在编译连接的时候,会处理好这个问题,使得同一份代码尽量在 app 中仅保留一份。
但如果开发人员使用不恰当或者配置错误,很可能导致出现两份 T 源码在项目中。
这个时候如果版本还不兼容,就会有非常大的调试和异常隐患。
模块隔离方案:修改 Product Name,将 T 变成 TT 模块
然后,还需要考虑将 TT 变成静态库还是动态库:

静态库:

这是完全去开源的方案。变成静态库后,TT 源码将打入 framework 二进制中一起提供。因为模块隔离,外部也无法调用和感知。

  • 通过对 framework 二进制字符表进行分析,还是能够看到 T 的踪迹。
  • 如果不做模块隔离,也能成功。主 app 也使用 T 模块的时候,链接的时候将自动保留 1 份静态代码。有版本差异的话,出现异常问题将非常难以排查。

动态库:

使用动态库的话,如前面【需要提供多个 framework】所描述的,有两种方案:

  • TT 可以提供给业务,让业务自行接入。是 flat 平铺 结构。
  • 也可以内嵌到 m framework 的 frameworks 文件夹中专门供 m framework 使用。是 内嵌 结构。
    • 如果不做模块隔离,也可以内嵌。但主 app 可能也使用了 T 模块,使得同一个工程包含 2 个版本的 T 模块,运行的时候按照 xcode 编译顺序,只有一份被使用。有版本差异的话,出现异常问题将非常难以排查。