几天前,Epic Games 与 Apple 案迎来了一项重要裁决。法官认定 Apple 故意违反了法院于 2021 年发布的反垄断永久禁令,表面上虽允许开发者使用第三方支付渠道,但却通过高额佣金、用户体验障碍以及警告页面等方式,实质上继续维护着原有的市场垄断地位。法院不仅批准了 Epic 提交的执行禁令动议,还罕见地将 Apple 的行为移交给美国司法部加州北区检察官,以调查其是否构成刑事藐视法庭。
苹果凭借 iPhone 和 App Store 建立起牢固的商业壁垒,曾经那家特立独行、以创新为骄傲的企业,如今却逐步转变成它自己也曾试图避免的科技巨头。随着公司体量与市场影响力的增加,苹果逐渐从追求创新转向对市场地位的保护和防御,这本身并不奇怪——当企业规模足够大时,保护自身市场优势的收益,往往比不断投入不确定的创新更具吸引力。
App Store 的分成比例合适与否,完全取决于其给软件开发者带来的实际价值和服务。对于小型尤其是独立开发者来说,尽管佣金比例不低,但 App Store 提供的全球支付渠道、可信任的分发平台,以及便捷的推广手段,使它们能够相对容易地实现稳定的收入。但对于那些具备自主宣传渠道和广泛用户基础的大型科技公司而言,仅因通过 App Store 分发就被抽取高昂比例的收入无疑难以接受,这也是近年来苹果不断遭遇开发者和监管机构挑战的核心问题。
可以预见,本次裁决无疑会进一步加快全球各地监管、立法机构的跟进步伐,苹果“轻松收取过路费”的时代或将一去不复返。
苹果一直未能彻底摆脱以硬件为主导的发展路径,缺乏足够强大的网络服务吸引力,难以为生态内的开发者提供令人信服的增值服务。对于大量专注于苹果生态的开发者来说,他们天然倾向于使用苹果第一方的 API 和服务。苹果完全有能力通过提供更高效稳定的云端服务、更丰富且易用的大模型 API,甚至竞争力更强的 AI 云计算服务,来进一步增强自身生态的吸引力,并以更加令开发者认可的方式获得收益。然而,苹果迄今尚未迈出这关键一步。
本次裁决对苹果而言,不仅仅是对其傲慢姿态的警醒,更深刻揭示了其长期以来在生态建设中缺乏同理心、居高临下的态度所带来的必然反噬。希望这一教训能真正促使苹果重新审视自身生态战略,摒弃防御心态,以更加主动、开放、包容的姿态面对开发者社区,充分发挥自身技术与服务优势,重塑开发者的信任与合作热情。唯有如此,App Store 才能重回正轨,成为一个开发者、用户与平台方均能实现长期共赢的繁荣生态。
原创
使用 equatable() 避免 NavigationLink 预构建陷阱
NavigationLink
是 SwiftUI 开发者非常喜欢使用的一个组件,它巧妙地结合了 Button
和导航跳转逻辑,大大简化了代码实现。但在某些场景下不恰当地使用它可能会导致严重的性能问题,使应用响应变得迟缓。本文将尝试分析这个问题的成因,并提供一个实用但略显神秘(无奈)的解决方案——使用 equatable()
修饰器来优化性能。
近期推荐
Swift 6.1 新特性速览 (What’s New in Swift 6.1?)
在之前的周报中,我已经推荐过多篇介绍 Swift 6.1 新特性的优秀文章。但当我读到 Paul Hudson 的这篇总结时,仍然发现了一些此前没有注意到的细节。其中,Metatype Keypaths 就是我当前项目中急需的能力,它使得我们可以使用 key path 访问类型的静态属性,不再受限于实例成员。此外,我最近在测试中使用的 #expect(throws:)
特性,也是在阅读本文后才意识到是 Swift 6.1 的新增功能。它的 API 调整让错误判断逻辑更加直观,减少了嵌套闭包的复杂度。
用 Mutex 保护可变状态 (Protecting Mutable State with Mutex in Swift)
actor
是保护共享可变状态的首选方案之一,但并不总是最佳选择,特别是当你不希望引入异步代码时。Swift 6 中新增的 Mutex
类型,提供了一种更符合现代并发模型的同步锁工具。Donny Wals 在本文中详尽介绍了 Mutex 的使用方式,并指出在某些情况下,Mutex
可能是更合适、更轻量的选择:
- Mutex 是阻塞式的,适合用于快速、同步的状态访问;
- 使用 Mutex 不会强制引入异步调用,因此不会干扰调用栈结构;
- Mutex 本身符合
Sendable
,可以很好地融入 Swift 6 的并发模型。
实现后台下载 (Keep Downloading with a Background Session)
从 iOS 7 开始,开发者便可以通过 URLSession
的 background
类型 session 实现断点续传与下载任务恢复。即使到了 Swift 6,Apple 仍未提供基于 async/await
的封装。在本文中,William Boles 详细介绍了 background session 的使用方式,并清楚解释了为什么这类任务不能直接支持 async/await
。简单来说,background session 使用系统守护进程(nsurlsessiond
)在 app 被挂起或终止后继续处理任务,而 async/await
则依赖于进程内的调用栈与任务树。两者运行机制不同,天然不兼容。
基于 Task Local 构建依赖容器 (Dependency Container on Top of Task Local Values in Swift)
Swift 的 @TaskLocal
属性为当前 Task 及其子任务提供了一种隐式的上下文传递机制。虽然这一特性使用频率不高,但在异步环境中,它是一种优雅的状态注入方式。Majid Jabrayilov 在本文中展示了如何基于 Task Local 构建一个依赖注入容器,适用于需要良好依赖隔离、又不希望依赖全局单例的场景。
值得一提的是,Swift 6.1 引入的 Test Scoping Traits 也是基于
@TaskLocal
实现的,它们在测试场景中可以很好地配合使用,构建出清晰可控的异步上下文环境。
深度链接实践全解 (Deep or Not Too Deep)
深度链接(Deep Linking)是提升用户体验、实现跳转归因与上下文还原的关键机制。随着移动系统的发展,Deep Linking 的实现方式也在不断演进。kyryl horbushko 在这篇内容详实的长文中,系统回顾了 iOS 与 Android 平台上深度链接的演进历史与原生实现方式,并深入讲解了如何借助 AppsFlyer 实现 deferred deep link 与归因跟踪。这是一篇值得收藏的参考资料。
🪜 用 Metal + SwiftUI 构建波动发光按钮 (Oscillating Glowing Strings with Metal and SwiftUI)
一如既往,Uladzislau Volchyk 再次带来一篇精彩的 SwiftUI + Metal 视觉实验。本文通过 colorEffect
与自定义 shader 打造出一个具有波动发光效果、可响应交互的按钮,并融合了 spatialWrap
、haptic feedback 等 SwiftUI 技巧,为视觉层次和交互体验增添了更多细节。
工具
Chord Provider
ChordPro 是一种用于编排歌词与和弦的文本标记格式,而 Nick Berendsen 开发的 Chord Provider,则是一个专为 macOS 打造的原生开源 ChordPro 文件编辑与阅读器。项目完全采用 Swift 6 与 SwiftUI 编写,无任何第三方依赖。对 macOS 程序员而言,Chord Provider 涵盖了 DocumentGroup
管理、CoreAudio
播放、SwiftUI 多种布局能力等诸多实践细节,是一个值得参考的典范项目;而对吉他爱好者来说,它则是一款简洁自然、专注体验的桌面伴侣。
NSAlchemy:扩展 SwiftUI 的 macOS 控件库
尽管 SwiftUI 近年来在 macOS 平台上不断扩展,但依旧缺少不少关键控件。为此,Joshua J. Root 开发了 NSAlchemy —— 一个将常用 AppKit 控件封装为 SwiftUI 组件的库。当前版本中已包含 HSlider
、VSlider
、CircularSlider
、LevelIndicator
、PathControl
、ComboBox
、Checkbox
、AcceleratorButton
、ContinuousButton
、SearchField
、SegmentedControl
等组件,适用于构建更完整、更具原生感的 macOS 应用。
VS2X: VSCode 主题转换器
相较于 Xcode,VSCode 拥有更丰富的主题生态,用户社区也更热衷于分享与自定义。为此,Wei Wang (onevcat) 推出了一款在线工具,可将喜爱的 VSCode 主题一键转换为 Xcode 可用的格式。项目完全由 AI 驱动生成,作者也 开源了全部代码。对于这种目标明确、功能聚焦的应用场景,大模型的确已经具备了令人惊喜的实用性。