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

推荐订阅源

S
Security @ Cisco Blogs
H
Hacker News: Front Page
P
Privacy International News Feed
N
News and Events Feed by Topic
T
Threatpost
Simon Willison's Weblog
Simon Willison's Weblog
S
Schneier on Security
K
Kaspersky official blog
S
Secure Thoughts
V2EX - 技术
V2EX - 技术
Security Latest
Security Latest
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
www.infosecurity-magazine.com
www.infosecurity-magazine.com
C
CERT Recently Published Vulnerability Notes
L
Lohrmann on Cybersecurity
Jina AI
Jina AI
P
Proofpoint News Feed
AI
AI
雷峰网
雷峰网
T
Tailwind CSS Blog
Engineering at Meta
Engineering at Meta
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Recent Commits to openclaw:main
Recent Commits to openclaw:main
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
博客园 - 叶小钗
Webroot Blog
Webroot Blog
Apple Machine Learning Research
Apple Machine Learning Research
SecWiki News
SecWiki News
罗磊的独立博客
N
Netflix TechBlog - Medium
Martin Fowler
Martin Fowler
Google DeepMind News
Google DeepMind News
Cyberwarzone
Cyberwarzone
MongoDB | Blog
MongoDB | Blog
博客园 - Franky
Schneier on Security
Schneier on Security
The GitHub Blog
The GitHub Blog
S
Security Affairs
Blog — PlanetScale
Blog — PlanetScale
Last Week in AI
Last Week in AI
P
Proofpoint News Feed
月光博客
月光博客
D
Docker
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
Securelist
W
WeLiveSecurity
T
Troy Hunt's Blog
A
Arctic Wolf
博客园 - 司徒正美

肘子的 Swift 记事本 | Fatbobman's Blog

当灵感跑在了结果前面 -- 肘子的 Swift 周报 #145 当每一次写入都有了新价格 -- 肘子的 Swift 周报 #144 当 Linux 成为“空气”:容器、Agent 与不再重要的“桌面之争” -- 肘子的 Swift 周报 #143 两个 SwiftUI 动画 Bug 排查小记 SPI 加入 Apple,Swift 迈向自举 -- 肘子的 Swift 周报 #142 Swift 还让你 Excited 吗? -- 肘子的 Swift 周报 #141 从 Size Class 到可用空间,horizontalSizeClass 还可靠吗? WWDC 26:AI 帮你看完了,然后呢? -- 肘子的 Swift 周报 #140 WWDC 2026 初印象:符合预期,但更务实 -- 肘子的 Swift 周报 #139 Core Data + Observation:从属性级响应到心智解放 稳定 > 新功能 -- 肘子的 Swift 周报 #138 用自定义 Layout 化解 SwiftUI List 的行高与间距跳变 从社区路标到生态基石:Dave Verwer 的新篇章 -- 肘子的 Swift 周报 #137 消失的 WWDC 愿望单 -- 肘子的 Swift 周报 #136 CocoaPods 正在退场,SwiftPM 才刚到第二章 -- 肘子的 Swift 周报 #135 让 AI 从称手到称心 -- 肘子的 Swift 周报 #134 Swift 并发正被更广泛地接纳 -- 肘子的 Swift 周报 #133 从 OpenSwiftUI 到 DanceUI:换个方式 Dive SwiftUI -- 肘子的 Swift 周报 #132 被 Vibe 摧毁的版权壁垒,与开发者的新护城河 -- 肘子的 Swift 周报 #131 苹果的罕见妥协:当高危漏洞遇上“拒升”潮 -- 肘子的 Swift 周报 #130 一墙之隔,不同的时空 -- 肘子的 Swift 周报 #129 我的 App 审核被卡了? -- 肘子的 Swift 周报 #128 CDE:一次让 Core Data 更像现代 Swift 的尝试 50 岁的苹果和 51 岁的我 -- 肘子的 Swift 周报 #127 2026 年,为什么我仍在思考 Core Data Macbook Neo:苹果重回校园的起点 -- 肘子的 Swift 周报 #126 跨域传递 NSManagedObjectContext 为什么在 Swift 6.2 中不再报错?真正的变化不在编译器 Xcode 26.3 + Claude Agent:模型替换、MCP、Skill 与自适应配置 macOS 录屏软件开发实录:从像素抓取到元数据重现 isolated(any) 与 #isolation:让 Swift 闭包自动继承隔离域 在 tvOS 上活下來:一個非典型播放器的工程實錄 告别“可移植汇编”:我已让 Swift 在 MCU 上运行七年 独立开发者的试炼:Zipic 从 0 到 1 的产品化之路 逃离 Mac App Store:如何从零构建独立应用的分发与售卖体系 为什么父视图无法修改子视图的 @State Partytown 实战:修复 GTM 自定义事件与 dataLayer 失效问题 Swift 6 编译加速:启用 Swift-Syntax 预构建 (Prebuilts) Monorepo 实战:解决 VSCode/Cursor 中 SwiftLint 配置失效问题 VSCode/Cursor 测试 Core Data:手动编译 xcdatamodeld 指南
Swift 模块化:使用 package 关键字实现 Target 间安全共享
东坡肘子 · 2025-05-08 · via 肘子的 Swift 记事本 | Fatbobman's Blog

Read in English

🔋

(更新于 )

核心摘要:Swift 的 package 访问修饰符允许开发者在同一个 Package 内的多个 Target 之间共享 API,同时对 Package 外部保持不可见。它有效解决了模块化开发中 internal 权限过窄、public 权限过宽的痛点,是构建复杂 SPM 依赖树的标准实践。

Swift 5.9 引入的 package 访问控制修饰符,旨在将 API 访问范围限定在同一 Package 内(含多个 Target),避免使用 public 造成过度暴露。此功能特别适用于模块化结构中需要在多个 Target 之间共享实现但不希望对外开放的场景,提升封装性和安全性。

背景

随着模块化编程的普及,开发者越来越倾向于通过 Swift Package Manager(SPM)将不同功能拆分为多个 Package。进一步地,同一个 Package 又常被细分为多个 Target。在这种结构中,如何限制 API 仅在 Package 内部(包括不同 Target)使用,同时避免使用 public 将其暴露给外部,是一个常见的需求。

package 关键字的引入

package 关键字指定 API 的可见范围仅限于同一个 Package 内的不同 Target,从而无需将内部实现暴露给外部模块。这填补了 internal(仅模块内可见)和 public(完全公开)之间的空白。

public struct MyStruct {
    public init() { ... }
    public var name: String { ... }
    
    // 仅在同一个 Package 内的其他 Target 中可访问,外部不可见
    package func action() { ... } 
}

实际应用场景

以某项目中的 Persistent Package 为例,该 Package 处理所有数据持久化相关功能,并拆分为多个 Target:

Project
├── Domain
│   └── Package.swift
└── Persistent
    ├── Package.swift
    └── Sources
        ├── Models       (Target)
        ├── CURD         (Target)
        └── Stack        (Target)

Domain Package 中,定义了线程安全的 ViewModel 转换协议:

public protocol ViewModelConvertible {
    associatedtype Value: ViewModelProtocol
    
    @MainActor
    func convertToViewModel() -> Value
}

由于 NSManagedObject (Core Data) 并非线程安全,在 Persistent Package 内部处理 ViewModel 转换时,可能无法直接满足 @MainActor 的限制。因此可以在 Persistent 的任意 Target 中定义如下协议:

package protocol ViewModelConvertibleUnsafe {
    associatedtype Value: ViewModelProtocol
    
    // 仅供 Package 内部使用的非安全接口
    func convertToViewModelUnsafe() -> Value
}

通过使用 package 修饰,该协议仅在 Persistent Package 内部的 Target 间共享,确保内部逻辑的灵活性与外部接口的安全性。外部模块依旧通过线程安全的 convertToViewModel() 接口进行调用。

延伸阅读

相关提示

订阅 Fatbobman 周报

每周精选 Swift 与 SwiftUI 开发技巧,加入众多开发者的行列。

立即订阅