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

推荐订阅源

博客园_首页
Vercel News
Vercel News
月光博客
月光博客
S
SegmentFault 最新的问题
A
About on SuperTechFans
Microsoft Security Blog
Microsoft Security Blog
U
Unit 42
Google DeepMind News
Google DeepMind News
Engineering at Meta
Engineering at Meta
B
Blog RSS Feed
Y
Y Combinator Blog
云风的 BLOG
云风的 BLOG
N
Netflix TechBlog - Medium
小众软件
小众软件
WordPress大学
WordPress大学
G
Google Developers Blog
Recent Announcements
Recent Announcements
H
Hackread – Cybersecurity News, Data Breaches, AI and More
P
Proofpoint News Feed
Blog — PlanetScale
Blog — PlanetScale
MongoDB | Blog
MongoDB | Blog
F
Fortinet All Blogs
博客园 - 【当耐特】
I
InfoQ

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

从 pbxproj 到 xcproj:Xcode 工程配置迎来 JSON 格式 iPhone Duo 带来的机遇与挑战 -- 肘子的 Swift 周报 #153 当 Mac mini 的价格不再 mini -- 肘子的 Swift 周报 #152 SwiftData:优化从建模开始 举手之劳 -- 肘子的 Swift 周报 #151 从使用 AI 到委托 AI(下):我想要的可委托性 AI 想放弃了,人没有 -- 肘子的 Swift 周报 #150 从使用 AI 到委托 AI:我的一些思考 越来越慢的 App Review,拦住了谁? -- 肘子的 Swift 周报 #149 ContentBuilder 解析:SwiftUI 类型检查性能提升的秘密 Apple Intelligence 已通过中国政府审核,即将在中国提供服务 -- 肘子的 Swift 周报 #148 在 SwiftUI Text 中控制孤行:挖掘未公开的 avoidsOrphans 热茶还是冰咖啡 -- 肘子的 Swift 周报 #147 Liquid Glass:UIKit 适配踩坑实录 不是模型变慢了,是任务变大了 -- 肘子的 Swift 周报 #146 当灵感跑在了结果前面 -- 肘子的 Swift 周报 #145 当 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 周报 #144
Fatbobman · 2026-07-13 · via 肘子的 Swift 记事本 | Fatbobman's Blog

最近,OpenAI 的 Codex 被发现存在一个日志写入问题:程序会持续向本地数据库写入大量日志,导致文件不断膨胀,并产生远超正常水平的磁盘写入。类似的 Bug 过去并不少见。放在几年前,人们大概只是删除文件、重启应用,然后等待下一个版本修复。

但这一次,大家的反应明显不同。比起“还剩多少磁盘空间”,更多人开始关心 SSD 已经累计写入了多少数据,会不会影响闪存寿命,以及未来更换设备时,需要为同样容量的内存和存储多付多少钱。

Codex 的 Bug 未必比过去那些失控的日志程序更加严重。真正发生变化的是:每一次无意义的写入,似乎都重新有了价格。

随着 AI 算力需求迅速增长,存储器厂商越来越倾向于优先保障 HBM、服务器内存和企业级 SSD 等利润更高、需求更旺盛的产品。消费级内存和 SSD 能够分配到的产能因此受到挤压,价格也不断走高。

内存和闪存本来就是典型的周期性行业,价格上涨和下跌并不罕见。但这一轮变化令人不安的地方,在于它似乎不再只是一次简单的库存周期,而是伴随着产业资源向 AI 基础设施长期倾斜。

即使价格最终仍会回落,消费者恐怕也很难迅速回到过去那种“大容量近乎免费”的心理预期。

当存储不再显得取之不尽时,开发者或许也应该转变对资源时的态度。

在我最开始接触电脑时,Apple II 常见的内存配置只有 48 KB。为了使用扩展卡额外提供的 16 KB 空间,开发者需要仔细安排地址、代码和数据,想方设法把每一个字节都利用起来。

今天一个数十 GB 的游戏,必然拥有 FC 时代无法想象的画面、声音、世界规模和交互复杂度。然而,巨大的容量并不能保证它带来的乐趣一定超过一个只有几十 KB 的游戏。

这并不是说现代软件不应该变大。真正值得思考的是,在过去很多年中,开发者已经习惯了存储容量会自然增长、网络会不断变快。日志、缓存和临时数据只要暂时还放得下,就很少有人追问它们为什么存在,又将在什么时候被删除。

昂贵的 SSD 不会自动创造优秀的软件,内存短缺也不会让开发者突然变得更加聪明。但当硬件不再被默认会无限增长时,那些曾经被忽视的工程问题便会重新浮出水面。

我并不怀念那个需要在几十 KB 中反复腾挪的时代。

真正值得重新拾起的,并不是资源匮乏,而是那种曾经十分自然、后来却逐渐消失的工程习惯:

知道每一个字节为什么到来,也知道它将在什么时候离开。

近期推荐

iOS 设备锁定后,Swift Task 能运行多久?(Swift Task lifetime when an iOS device is locked)

这是一篇来自 Apple Developer Forums 的问答。提问者发现,一个会串行执行多个 REST 请求的 Swift Task,在设备锁定后有时能够正常完成,有时会暂停,甚至出现超时。DTS 工程师 Quinn “The Eskimo!” 解释道,Swift Concurrency 完全运行在应用进程中;一旦 iOS 挂起进程,执行 Task 的工作线程也会停止,Task 本身并不会获得额外的后台运行能力。

这种机制在网络请求中尤其容易造成困惑。应用被挂起时,正在进行的 URLSession 请求可能因连接失效而失败;进程恢复后,开发者看到的可能是请求超时或网络错误,而不是 Task 从暂停处继续并顺利完成。Quinn 给出了四种处理方向:设法延缓进程挂起、在应用即将被挂起时停止请求、允许请求失败并做好重试与错误恢复,或者使用 URLSession 的后台会话。


Swift 6.4 中的 anyAppleOS (anyAppleOS in Swift 6.4)

过去,为跨 Apple 平台共享的 API 声明可用性时,开发者需要分别列出各个平台及其对应的系统版本。由于不同平台的版本号长期不一致,这类声明不仅冗长,也容易出现遗漏或版本填写错误。随着 Apple 各平台从 26 开始统一版本号,Swift 6.4 引入了 anyAppleOS,允许开发者在 @available#available#if os(...) 中,以更简洁的方式描述适用于 Apple 操作系统的 API 与代码。

Artem Mirzabekian⁠ 介绍了这一新语法,并梳理了它与平台专属可用性、canImport 以及 Package.swift 平台声明之间的区别,同时说明了如何结合更具体的可用性规则,处理部分平台延后支持或完全不可用的情况。


可复用 SwiftUI 视图的设计剖析 (The Anatomy of a Reusable SwiftUI View)

越来越多的开发者在构建可复用 SwiftUI 视图时,都希望其 API 尽可能贴近 Apple 官方的设计方式,但具体如何落地,往往缺少一套清晰的方法。Alexander Weiß⁠ 给出了自己的设计思路:首先判断组件属于描述功能概念的语义型组件,还是具有明确视觉形态的规定型组件,再梳理其语义、合法状态、数据流与交互行为。同时,组件还应遵循 SwiftUI 的状态管理方式,正确使用不可变值、Binding 与 State,并将无障碍支持、环境值和视图身份稳定性纳入设计,而不只是关注 API 的调用形式。

文章通过 Card、Tag 和 Rating 三个示例展示了初始化方法、自定义 View Style 和环境值等具体实现。这套方法的核心并非简单模仿 Apple API 的外形,而是让自定义组件在组合方式、状态流转、交互行为、无障碍支持和环境适配等方面真正融入 SwiftUI 体系。


SwiftUI 环境默认值不稳定的隐性成本 (The hidden cost of unstable SwiftUI environment defaults)

@Entry 宏让自定义环境值的声明更加便捷,但如果直接将引用类型实例作为默认值,例如 @Entry var logger = AppLogger(),就可能带来不必要的视图更新。每当 SwiftUI 没有找到上层注入的值而回退到默认值时,都可能重新创建一个 AppLogger。这些对象虽然功能相同,却不是同一个实例,因此 SwiftUI 会认为环境值发生了变化,进而重新计算读取它的视图。Xcode 27 开始会针对这种写法发出警告,让这个过去不易察觉的问题更早暴露出来。

Natalia Panferova⁠ 使用 _printChanges() 直观展示了这一问题,并给出两种解决方式:将默认实例保存在稳定的外部存储中,或者将环境值声明为 Optional,再由应用入口显式注入。

我在《SwiftUI Environment:理念与实践》中也分析过这一问题。其根源在于 @Entry 宏生成默认环境值的方式,使默认表达式可能在回退访问时被重复求值。


使用 visualEffect 为 SwiftUI ScrollView 创建纵向视差效果 (Make Vertical Parallax for ScrollView in SwiftUI)

早期的二维游戏通过让不同图层以不同速度移动,用很低的成本便营造出了富有层次感的视觉效果。但在 SwiftUI 中实现滚动视差,真正麻烦的通常不是计算偏移量,而是持续获取每个视图在 ScrollView 中的位置。过去,这类效果往往需要结合 GeometryReader、自定义坐标空间和状态传递来完成,不仅代码量较大,处理不当还可能引发额外的视图更新。

visualEffect 的引入大幅降低了这类效果的实现难度。codelaby⁠ 展示了如何直接在 visualEffect 中读取视图的几何信息,并根据滚动位置应用 offset,无须额外维护状态,也不会改变视图原有的布局。

工具

swift-span-algorithms: 给 Span 补上算法能力

在处理连续内存时,Swift 过去主要有两类选择:使用 ArrayContiguousArray 等拥有存储的容器,安全易用,但可能伴随复制、引用计数或额外分配;使用 UnsafeBufferPointer 等指针类型,成本低、控制力强,却需要开发者自行保证内存仍然有效,并避免越界访问。

Swift 6.2 新增的 Span<Element> 填补了两者之间的空白。它是一段连续内存的非拥有视图:不持有底层存储,却能借助编译器追踪生命周期,并通过边界检查提供安全访问。不过,在 Swift 6.2 中,Span 尚未拥有 Collection、Sequence 那般完整的算法能力。

David Retegan 开发的 swift-span-algorithms 正是对这一缺口的补充。它为 Span、RawSpan、MutableSpan 和 InlineArray 提供查找、比较、修剪、分块、滑动窗口、切分及游标(Cursor)等操作。整个库零以无隐藏分配和常数级额外空间为设计目标,在扩展算法能力的同时,仍然遵守 Span 的生命周期约束。