Issue #115

周日小插曲

Cover for Weekly Issue 115

周日下午,我正准备周一的周报。起身的瞬间,右手小指似乎碰到了什么,然后它就伸不直了。

有些诡异——不痛、不肿,但就是无法伸直。急诊医生初步判断是小指伸肌腱损伤,约了周一做进一步检查,很可能需要手术修复。

这才意识到,平时存在感不强的小指,原来如此重要。现在戴着固定指套,打字变得比较困难。好在应该不是什么大问题,只是接下来一段时间会减少打字量。

人生无常,微笑对待。

周一更新:今天进一步检查后,发现没有需要复位的骨折,只是单纯的肌腱断裂。这样就不用手术了,只需要戴指套固定 6 周就基本能恢复了。

近期推荐

从 YaoYao 到 Tooboo:watchOS 开发避坑与实战

作为知名 watchOS 应用 YaoYao、Tooboo、DunDun 的作者,Haozes 分享了 watchOS 开发中关于版本兼容、App 唤起通信、数据同步、重启恢复、内存泄露和电量优化等高质量实战经验。这篇文章涵盖了从 HealthKit 到 WCSession、从 HKWorkoutSession 到 TimelineSchedule 的完整开发避坑与性能调优指南,对于正在开发或计划开发 Apple Watch 应用的开发者具有极高参考价值。

作为一个长期的 Apple Watch 用户和 Swift 博主,我常感叹 watchOS 开发的“神秘”——文档之外细节繁多,且网络上真正有深度的实战文章寥寥无几。为此,我特别邀请了 watchOS 领域的头部独立开发者 Haozes,来分享他的开发体会。


Swift 6 严格并发迁移实战 (My journey to Swift 6 and Strict Concurrency)

一次“只在真实用户设备上才会出现”的崩溃,迫使 Irving Popovetsky 将一整个已上线的 iOS 应用迁移到 Swift 6 + Strict Concurrency。这篇文章完整记录了从迁移之初的 76 个 error、238 个 warning 开始,到逐步引入 @preconcurrencyactor@MainActorSendablenonisolated(unsafe),再到真机 + Thread Sanitizer 验证的全过程。Irving 指出,Swift 6 的运行时会在闭包被调用的瞬间验证 actor 隔离,哪怕你在闭包内部再 Task { @MainActor in } 也可能为时已晚。文章中对这一行为给出了清晰、可复用的修复模式。


用 MetricKit 监控应用性能 (Monitoring app performance with MetricKit)

MetricKit 是 Apple 在 iOS 13 引入的系统级性能诊断框架,用于向开发者提供来自真实用户设备的应用性能与稳定性数据。它只在真机环境中工作,数据来源于系统在后台长期采样并聚合的结果,因此能够更真实地反映应用在实际使用场景下的行为。

Majid Jabrayilov 在本文中展示了如何通过 MXMetricManager 订阅系统级性能数据,从后台异常退出、CPU / 内存资源限制,到崩溃诊断信息,逐步提取关键指标并上报,从而构建一个更完整、可追溯的应用性能监控面板。Majid 也特别提醒,MetricKit 的数据通常按天聚合下发,而非实时回调,实际分析时需要结合时间戳理解其所覆盖的时间区间。


用 Claude Code 重构 MistKit (Rebuilding MistKit with Claude Code - From CloudKit Docs to Type-Safe Swift)

Leo Dion 在重建自己停更多年的 CloudKit 服务端库 MistKit 时,发现 swift-openapi-generator 能显著降低重构复杂度:只要将 CloudKit 的 REST 文档转化为 OpenAPI 规范,就可以自动生成大规模、类型安全的 Swift 客户端代码。为此,他引入 Claude Code,专门负责完成“从 Apple 文档到 OpenAPI YAML”的翻译工作。

文章最有价值的地方,并不在于“AI 生成了多少代码”,而在于 Leo 如何使用 AI。他并没有让 Claude 直接实现 MistKit,而是将其定位为“文档翻译与模式放大器”,而真正复杂、需要工程判断与架构取舍的部分,始终由作者亲自把控。与其让 AI 直接“写代码”,不如让它把复杂问题变成可生成、可校验的问题——这正是这次 MistKit 重建过程中最值得借鉴的地方。


ChatGPT 记忆系统逆向分析 (I Reverse Engineered ChatGPT’s Memory System, and Here’s What I Found!)

Manthan Gupta 通过大量对话实验,对 ChatGPT 的“记忆”行为进行了逆向分析,发现其实现方式远比想象中简单:没有向量数据库、没有跨历史对话的 RAG,而是由四层上下文共同构成——一次性注入的 Session Metadata、显式存储的长期用户记忆、近期对话的轻量摘要,以及当前会话的滑动窗口。Manthan 认为,这种设计在性能、延迟和 token 成本上的优势非常明显:通过预计算摘要和显式事实注入,换取“足够好”的连续性,而不是昂贵的全量历史检索。Manthan 还有另一篇针对 Claude 记忆系统的研究

在使用 ChatGPT 的过程中,我时常会对它对我的了解程度感到惊讶。尽管我清楚,这种“熟悉感”来自其记忆与上下文机制,但这也正是我长期偏向使用官方客户端的重要原因之一。当然,如果你对隐私问题格外敏感,那么这种能力本身,可能正是你不愿接受的那一部分。


Swift Configuration 1.0 released

Honza Dvorsky 在 Swift 官方博客中宣布 Swift Configuration 1.0 正式发布。该库为 Swift 应用与库提供了一套统一、类型安全的配置读取抽象,其关键并不在于支持多少配置格式,而是彻底分离「配置如何读取」与「配置来自哪里」。这一设计对库作者尤为重要——库可以接受配置而不绑定具体来源,从而在不同部署环境中保持良好的可组合性。随着 1.0 发布,Swift Configuration 的 API 已进入稳定阶段,并开始被 Vapor、Hummingbird 等项目探索集成。

乍看之下,为配置管理引入这样一个抽象层似乎显得有些“重量级”,但一旦配置来源不再局限于单一文件,或者代码需要在不同环境与项目中复用,其带来的结构清晰度与扩展性优势就会迅速显现。


TCA 架构:一个被美化的反模式? (TCA Architecture: A Glorified Antipattern)

这是一篇立场极其鲜明的长文。Lazar Otasevic 从函数式编程与 SwiftUI 的运行模型出发,系统性地反对了 TCA 以 Action enum + Reducer 为核心的设计,认为这是一种“将行为编码为数据”的经典反模式,并且不必要地夺走了 SwiftUI 原本应当拥有的状态所有权。与许多停留在情绪或偏好层面的“反 TCA”讨论不同,本文给出了一套完整、可运行的替代思路:将 State 视为纯数据、Logic 视为无状态的实现细节,并通过闭包(capabilities)暴露行为,从而在保持可测试性与可组合性的同时,更贴合 SwiftUI 的声明式数据流模型。

考虑到 TCA 刚出现的时期,很多开发者仍难以应对 ObservableObject 响应颗粒度不足、缺乏 @MainActorTask 等工具、异步调用高度依赖 Combine 的现实处境,TCA 确实有效解决了当时的一系列痛点。但随着 Swift 与 SwiftUI 的不断演进,TCA 中一些曾经突出的优势已不再明显,而其可组合性模型对不少开发者而言,使用与理解成本也依然不低。即便如此,TCA 仍然是许多开发者和团队已经适应并喜爱的开发范式——归根结底,适合自己的,才是最好的。

工具

FluidAudio: 为 Apple 平台打造的本地化音频 AI 工具包

FluidAudio 是一个专为 Apple 平台设计的 Swift 音频 AI SDK,提供完全本地化的语音识别、说话人分离、语音活动检测等功能,由 Brandon WengAlex Weng 主导开发。所有推理都在 Apple Neural Engine (ANE) 上运行,实现了低延迟、低功耗的音频处理能力。

核心特性:

  • 完全本地化:所有模型在设备端运行,无需网络连接,充分保护用户隐私
  • ANE 优化:充分利用 Apple Neural Engine,避免使用 GPU/MPS,降低 CPU 使用率和功耗
  • 开源透明:基于 MIT/Apache 2.0 许可的开源模型,可在 Hugging Face 获取
  • 易于集成:通过 Swift Package Manager 安装,API 设计简洁直观
  • 生产就绪:已被 Voice Ink、Spokenly、Slipbox、BoltAI 等知名应用采用

FluidAudio 支持自动语音识别(Parakeet TDT v3,25 种欧洲语言)、说话人分离(离线/在线双模式)、语音活动检测(Silero VAD)以及文字转语音(Beta)。在 M4 Pro 上,语音识别的实时系数可达约 190x,处理 1 小时音频仅需 19 秒。

如果你正在开发涉及语音处理的 iOS/macOS 应用,FluidAudio 绝对值得尝试。


SwiftUI 中的一大痛点,在于如何将多级路由、sheet、full-screen cover 以及 alert 等不同导航与展示机制统一管理。由 Corey Davis 开发的 Navigable 提供了一种更集中、可测试的解决方案:它将所有导航行为统一收敛到一个可观察的 NavigationState 中,作为唯一的状态来源。

通过这种方式,Navigable 能够在保持 type-safe 与现代 Swift(@Observable、Swift 6) 特性的同时,将导航逻辑从视图中剥离出来,支持复杂流程、深链以及单元测试。同时,它既支持声明式的视图构建,也允许通过命令式 API(如 push / pop)驱动状态变化,在复杂场景下更接近传统路由系统的可控性。

该库仍处在开发早期,但其实现思路值得持续关注。

相关周报

订阅 Fatbobman 周报

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

立即订阅