Fatbobman's Swift Weekly #110
Skip Fuse Now Free for Indie Devs!
Skip Fuse Now Free for Indie Devs!
Shortly after the Swift community released the official Android SDK preview, Skip announced that its Skip Fuse edition is now free for eligible indie developers to build Android apps.
Compared with Skip Lite, which has been free to use for independent developers for over a year, Skip Fuse represents a substantial technical leap. While Skip Lite transpiles Swift code into Kotlin, Skip Fuse directly leverages the official Swift SDK for Android to cross-compile Swift source code into native ARM binaries that run on Android. This means developers are no longer restricted to “Skip-aware” dependencies — they can now use any Swift package that compiles for Android.
According to Swift Everywhere, more than 2,000 Swift packages already support the Android platform, including popular libraries such as Alamofire, SwiftSoup, and swift-sqlcipher. In other words, Fuse mode allows developers to take full advantage of the standard SwiftPM ecosystem. This significantly broadens the range of usable dependencies while reducing the complexity of project migration and maintenance.
Architecturally, Skip Fuse adopts a hybrid approach: the business logic layer is compiled and executed as native Swift, while the SwiftUI DSL is translated at build time by the Skip Fuse UI module into Jetpack Compose code — providing a fully native user experience on Android. This approach preserves SwiftUI’s declarative syntax while adhering to Android’s design conventions.
This policy change may encourage many indie developers and small teams to favor solutions with cross-platform potential. Even developers focused primarily on Apple’s ecosystem might now consider introducing abstraction layers. This prepares their projects for future multi-platform expansion — even if they currently rely on some of Apple’s private frameworks.
Naturally, Skip’s definition of an “indie developer” comes with clear conditions: it applies only to individuals or teams of up to two people, with annual revenue below US $30,000, and it permits the release of one closed-source commercial app (open-source projects are unlimited). Even so, this policy opens the door for Swift developers to enter the Android market at virtually no cost — offering new opportunities for experimentation, growth, and revenue on a massive platform.
While more cross-platform Swift solutions are likely to appear in the future, Skip has already provided a clear and practical path for bringing Swift to the Android ecosystem. The community now looks forward to seeing similar, mature approaches extended to Linux, Windows, and even embedded platforms — laying a stronger foundation for Swift’s truly multi-platform future.
Previous Issue|Newsletter Archive
📢 Sponsor Fatbobman’s Swift Weekly
Promote your product to Swift & iOS developers across:
- Blog: 70,000+ monthly visitors
- Newsletter: 4,000+ subscribers, 53% open rate
Perfect for developer tools, courses, and services.
Enjoyed this issue? Buy me a coffee ☕️
Recent Recommendations
The Art of SwiftData in 2025: From Scattered Pieces to a Masterpiece
With the removal of parent-child context concept, implementing “cancelable edits” in SwiftData has become increasingly challenging. In this comprehensive article, Mathis Gaignet demonstrates how to build a “cancelable, reusable, low-boilerplate” upsert architecture by constructing a dedicated ModelContext for editing state, replacing scattered form states and fragile rollback solutions.
Rather than presenting a “standard answer,” the author showcases the complete thought process from problem discovery to solution evolution. The article deeply explores the underlying mechanisms of @Model and @Query macros, reveals the traps of PersistentIdentifier‘s temporary and permanent states, and uncovers hidden bugs caused by context synchronization delays. This exploratory writing style helps readers understand not just “how to do it,” but “why it’s done this way.”
Back Market x Tuist - Part I: Why We Moved Our iOS Project To Tuist
In Swift projects, SPM handles both code modularization and project structure management. However, as projects scale, limitations emerge: frequent dependency resolution, lack of build settings and custom phases, inability to run scripts, xcodeproj file conflicts, difficulty unifying inter-module rules, and limited SPM plugin capabilities.
In this article, Alberto Salas explains how his team migrated project structure management from SPM packages to Tuist targets, systematically outlining the underlying issues, exploration process, and key decisions. In Part II, he further share how the migration was completed without disrupting daily development — and how it led to measurable improvements in build performance.
This isn’t about abandoning SPM entirely—project structure and generation are handed to Tuist while dependency management remains with SPM. The article compares SPM, Bazel, and Tuist trade-offs. The author notes that while Bazel is more powerful, they chose Tuist because it better matched their team’s capabilities and project characteristics. This reminds us that the key to tool selection isn’t “the strongest” but “the most suitable”—especially for small to medium teams, solutions that are self-manageable and maintainable often provide more long-term value.
Making Apps More Personal with Language Discovery
The traditional “select primary language” (Locale.preferredLanguages) model assumes users have a single language preference, but in reality, people often use multiple languages in different contexts—English at work, French socially, and Spanish for media consumption. Apple introduced Language Discovery in iOS 26, using on-device machine learning to automatically infer users’ language habits based on input patterns, content consumption, communication languages, and app preferences, all while ensuring privacy. Letizia Granata explains this intelligent system for recognizing user language preferences.
Through Language Discovery, apps can more accurately respond to users’ linguistic and cultural backgrounds, achieving personalization at the localization level. This feature marks an important shift in Apple’s multilingual support: from passive configuration to active understanding, from single language to multilingual coexistence, providing developers with a new foundation for building more inclusive and authentic app experiences.
Xcode 26.1 CPU Usage Issue: Warning and Temporary Workarounds
iOS developer Artem Mirzabekian reports that Xcode 26.1 experiences abnormal CPU usage when running the iOS 26.1 simulator. The issue stems from the wallpaper-rendering-related MercuryPosterExtension process repeatedly crashing and restarting in the iOS 26.1 simulator, causing excessive CPU consumption. Xcode 26.2 (beta) is also affected.
Temporary workarounds: Use the iOS 26.0 simulator, or change the wallpaper in the iOS 26.1 simulator and delete the default all-black wallpaper.
Swift 6 Concurrency Model: Technical Challenges and Community Debate
Michael Tsai compiled two important discussions about Swift 6 concurrency. The first focuses on Swift 6.2’s “Approachable Concurrency” improvements; the second addresses specific technical issues like the practical usage and limitations of MainActor.assumeIsolated and @preconcurrency.
Community opinions are clearly divided. Supporters believe that default main-thread isolation effectively prevents the common “accidentally running on background thread” problem, lowering the barrier for beginners and UI-intensive projects, with some teams successfully completing major app migrations. Critics point out that full UIKit apps still struggle to fully adopt Swift 6 mode, with frequent integration issues with Core Data and third-party frameworks, cryptic error messages, and ongoing language evolution causing code decay. More radical voices even argue the current concurrency model has become an “inoperable patchwork system” requiring a “complete reset.”
The overall consensus: Swift 6 concurrency benefits highly depend on a project’s concurrency complexity—it significantly helps single-threaded or UI-driven applications, but for concurrency-intensive or tightly system-coupled projects, migration remains challenging.
Deep Dive into Animation on visionOS
Spatial computing not only transforms user experience but also raises the bar for developers—many techniques effective in flat interfaces no longer apply in three-dimensional space. Starting from “spatial interaction perceptibility and comfort,” Cristian Díaz proposes an animation decision framework: who authors the animation (designer-crafted vs. runtime-generated), what needs animation (SwiftUI windows vs. RealityKit entities), and what complexity level (micro-interactions vs. choreographed performances). Building on this framework, he systematically outlines visionOS’s five rendering paths and ten animation mechanisms, clearly listing suitable scenarios, situations to avoid, and implementation essentials for each approach.
Even if you’re not a visionOS developer, you can benefit from this article. Cristian’s “deriving technical choices from perceptual needs” approach to animation design thinking applies equally to dynamic design on other platforms and interfaces.
Find the SwiftUI Views that Update the Most Using Instruments
Xcode 26 adds a SwiftUI-specific analysis tool to Instruments that tracks view update counts and duration, using All Updates Summary and Cause & Effect Graph to identify which views “update too frequently” and their specific trigger chains. Mark Szymczyk demonstrates through practical examples how to create SwiftUI Profiling sessions, sort views by update count/duration, and trace update sources using cause-and-effect graphs.
Beyond diagnosing symptoms, understanding SwiftUI’s refresh principles is essential for reducing unnecessary redraws at the source. In my article Understanding SwiftUI’s View Update Mechanism: Starting from a TimelineView Update Issue, I systematically explain view declarations, response mechanisms, and recursive update decision logic through a TimelineView case study. Only by understanding “why views update” and “how the system decides whether to recalculate view declaration values” can optimization avoid becoming patchwork fixes.
Tools
imessage-kit: Messaging Integration for AI Agents
imessage-kit is a powerful open-source iMessage SDK developed by Photon, ideal for integrating iMessage into AI agents or automation workflows. Key features include:
Modern API: Provides elegant chaining (Fluent API) for easily implementing “receive message A, reply B” logic
Comprehensive Functionality: Supports not only text sending/receiving but also images, various file types, and real-time message monitoring
Type-safe and Cross-runtime: Written entirely in TypeScript with excellent type support, compatible with both Node.js and Bun
AI Integration Friendly: Officially positioned to provide messaging integration capabilities for AI Agents, an interesting attempt at connecting the physical world with AI
It works by directly reading the iMessage database (chat.db) and combining AppleScript for automation, thus limited to macOS and requiring “Full Disk Access” permissions.
The library uses the SSPL-1.0 license, prohibiting use in creating competing products (like other messaging SDKs/APIs), but allowing use for internal business, personal projects, and educational purposes. Notably, Photon also offers an advanced version supporting threaded replies, message retraction/editing, live typing indicators, and enterprise-grade hosting services. More information available on their website.
SwiftUI-DetectGestureUtil: Bind Multiple Custom Gestures to a Single SwiftUI View
In SwiftUI, having a single view simultaneously recognize multiple gestures has always been challenging. Developed by Saw-000, SwiftUI-DetectGestureUtil introduces an independent “detection phase,” allowing developers to confirm only one among multiple custom gestures, bypassing constraints from default system combination methods (simultaneous, sequenced, exclusive) for more natural multi-gesture interactions.
It cleanly splits the gesture recognition workflow into two phases:
Detection Phase (
detectGesture): Continuously updates state throughout the gesture lifecycle until a custom rule matches and returns a gesture typeHandling Phase (
handleGesture): After detection, continuously tracks gesture progress, using.yetand.finishedto explicitly control the lifecycle
This model offers new approaches for building complex interactions (like “double-tap + drag,” “circle drawing,” “custom stroke detection”). With DetectGestureState, developers can access all touch points, timing, and geometric information within a single gesture cycle, achieving expressiveness and precision far exceeding SwiftUI’s native Gesture API.
Thanks for reading Fatbobman’s Swift Weekly! This post is public so feel free to share it.
Skip Fuse现在对独立开发者免费!
在 Swift 社区发布官方 Android 版 SDK 不久之后,Skip 宣布其 Skip Fuse 版本将对符合条件的独立开发者免费开放,用于构建 Android 应用。
与过去一年多独立开发者可免费使用的 Skip Lite 相比,Skip Fuse 带来了实质性的技术变革。Skip Lite 的原理是将 Swift 代码转译为 Kotlin,而 Skip Fuse 则直接利用 Swift 官方 Android SDK 进行交叉编译,将 Swift 源码编译为可在 Android 平台上原生运行的 ARM 二进制文件。这意味着开发者不再局限于“具有 Skip 感知”的依赖包,而可以使用任何能在 Android 上编译的 Swift 包。
根据 Swift Everywhere 的统计,目前已有超过 2000 个 Swift Package 支持 Android 平台,其中包括 Alamofire、SwiftSoup、swift-sqlcipher 等常用库。换句话说,Fuse 模式让开发者能够充分利用标准 SwiftPM 生态。这不仅显著拓宽了可用依赖的范围,也降低了项目迁移与维护的复杂度。
在架构层面上,Skip Fuse 采用了混合实现方案:业务逻辑部分由原生 Swift 直接编译执行,而 UI 层的 SwiftUI DSL 则在构建过程中由 Skip Fuse UI 模块映射为 Jetpack Compose 代码,从而在 Android 上呈现出完全原生的用户体验。这种做法既保留了 SwiftUI 的声明式语法,又遵循了 Android 平台的设计规范。
此次政策调整,或许会让许多独立开发者和中小团队在技术选型上更倾向于具备跨平台潜力的方案。即便继续主要面向 Apple 生态进行开发(使用苹果私有框架),也可能开始在架构中加入抽象层,为未来的多平台拓展预留空间。
当然,Skip 对“独立开发者”的定义也有明确限制:仅适用于个人或不超过两人的团队,年收入需低于 30,000 美元,并且免费许可仅允许发布一个闭源商业应用(开源项目数量不限)。即便如此,这一政策仍为 Swift 开发者以近乎零成本的方式进入 Android 市场打开了大门,为他们在这一庞大平台上探索新的可能与收入来源提供了契机。
尽管未来还会出现更多面向 Swift 的跨平台开发方案,但 Skip 已经为 Swift 在 Android 生态中的落地提供了一条清晰、可行的路径。社区也正期待着类似 Skip 这样成熟的跨平台方案能够扩展至 Linux、Windows 乃至嵌入式平台,为 Swift 的多平台发展奠定更坚实的基础。
如果您发现这份周报或我的博客对您有所帮助,可以考虑通过 爱发电,Buy Me a Coffee 支持我的创作。
近期推荐
SwiftData 的优雅取消编辑方案:从混乱到艺术 (The Art of SwiftData in 2025: From Scattered Pieces to a Masterpiece)
由于取消了父子上下文的概念,SwiftData 在实现“可撤销修改”方面变得更加棘手。Mathis Gaignet 在这篇长文中,通过构建一个专用于编辑状态的独立 ModelContext,阐述了在 SwiftData 中实现“可撤销、可复用、低样板”增改(Upsert)架构的思路,用以取代散乱的表单状态与脆弱的回滚方案。
作者并未直接给出“标准答案”,而是完整展示了从问题发现到方案演进的思考路径。文章深入解析了 @Model、@Query 宏的底层机制,揭示了 PersistentIdentifier 的临时与永久状态陷阱,以及上下文同步延迟导致的隐蔽 Bug。这种探索式的写作方式,使读者不仅明白“怎么做”,更理解“为什么这样做”。
从 SPM 项目管理迁移到 Tuist 项目管理 (Back Market x Tuist - Part I: Why We Moved Our iOS Project To Tuist)
在 Swift 项目中,SPM 除了负责代码模块化,也承担了项目结构管理的职责。然而,随着项目规模的扩大,这种方式的局限逐渐显现:依赖解析频繁、缺乏构建设置和自定义阶段、无法运行脚本、xcodeproj 文件易冲突、模块间规则难以统一,且 SPM 插件能力有限。Alberto Salas 在本文中介绍了其团队如何将项目结构管理从 SPM Packages 迁移至 Tuist Targets,并系统梳理了问题成因、探索路径与决策过程。在 Part II 中,他进一步分享了如何在不阻塞日常开发的前提下完成迁移,并量化了构建性能的提升。
本文并非要抛弃 SPM,而是将项目结构与生成工作交由 Tuist 接管,依赖管理依然由 SPM 负责。文章还比较了 SPM、Bazel 与 Tuist 的不同取舍。作者指出,Bazel 功能更强大,但最终选择 Tuist,是因为它更符合团队能力与项目特性。这也提醒我们,工具选型的关键不在“最强”,而在“最合适”——尤其对于中小型团队,可自主掌控、易于维护的方案往往更具长期价值。
让应用更懂用户语言:Language Discovery 的个性化新机制 (Making Apps More Personal with Language Discovery)
传统的“选择主要语言”(Locale.preferredLanguages) 模式假设每位用户都有单一语言偏好,但现实中人们往往在不同情境下使用多种语言——例如在工作中使用英语、在社交中使用法语、在媒体消费中使用西班牙语。苹果在 iOS 26 中添加了 Language Discovery 功能,通过设备端的机器学习,在确保隐私的前提下,基于用户的输入模式、内容消费、沟通语言以及应用偏好等行为数据,自动推断用户的语言使用习惯。Letizia Granata 在文中介绍了这一智能识别用户语言偏好的系统机制。
通过 Language Discovery,应用可以更准确地响应用户的语言与文化背景,从而在本地化层面实现个性化。这项功能标志着苹果在多语言支持上的一次重要转变:从被动配置走向主动理解,从单一语言到多语共存,为开发者提供了打造更包容、更真实应用体验的新基础。
关于 Xcode 26.1 CPU 异常占用的提醒和临时解决方案
iOS 开发者 Artem Mirzabekian 指出,Xcode 26.1 在运行 iOS 26.1 模拟器时会出现异常的 CPU 占用问题。原因是 iOS 26.1 模拟器中与壁纸渲染相关的 MercuryPosterExtension 进程持续崩溃并重启,导致 CPU 异常占用。Xcode 26.2(beta 版)目前也受影响。
临时解决方案:使用 iOS 26.0 模拟器,或在 iOS 26.1 模拟器中更换壁纸并删除默认的纯黑壁纸。
Swift 6 并发模型:技术挑战与社区争议
Michael Tsai 汇总了两组关于 Swift 6 并发的重要讨论。第一篇 关注 Swift 6.2 推出的 “Approachable Concurrency” 改进;第二篇 则聚焦具体技术议题,如 MainActor.assumeIsolated 与 @preconcurrency 的实际使用与限制;
社区观点呈现明显分化。支持者认为,默认主线程隔离有效防止了“意外跑到后台线程”的常见问题,降低了初学者与 UI 密集型项目的上手难度,一些团队已经成功完成大型应用的迁移。质疑者则指出,完整的 UIKit 应用仍难以全面采用 Swift 6 模式,与 Core Data 和第三方框架的集成问题频出,错误信息晦涩难懂,而语言的持续演进也让代码不断老化。更激进的声音甚至认为当前并发模型已成为“无法协同运作的拼凑体系”,需要一次“彻底重置”。
整体共识是:Swift 6 并发机制的收益高度依赖项目的并发复杂度——对单线程或 UI 驱动型应用帮助显著,但对于并发密集或系统耦合度高的项目,迁移仍充满挑战。
深入解析 visionOS 上的动画机制 (Deep Dive into Animation on visionOS)
空间计算不仅改变了用户体验,也对开发者提出了更高的要求——许多在平面界面中行之有效的技巧,在三维空间中已不再适用。Cristian Díaz 从“空间交互的可感知性与舒适性”出发,提出了一个动画决策框架:谁创作动画(设计师预制 vs. 运行时生成)、什么需要动画(SwiftUI 窗口 vs. RealityKit 实体)、复杂度如何(微交互 vs. 编排表演)。在此基础上,他系统梳理了 visionOS 的五条渲染路径与十种动画机制,为每种方案明确列出适用场景、避免情形与实现要点。
即便你并非 visionOS 开发者,也能从这篇文章中受益。Cristian 以“从感知需求推导技术选择”的方式诠释了动画设计思维,这种方法同样适用于其他平台和界面的动态设计。
使用 Instruments 找出 SwiftUI 中更新最频繁的视图 (Find the SwiftUI Views that Update the Most Using Instruments)
Xcode 26 为 Instruments 新增了 SwiftUI 专用的分析工具,可统计视图的更新次数与耗时,并通过 All Updates Summary 与 Cause & Effect Graph 定位哪些视图“更新过于频繁”以及具体触发链路。Mark Szymczyk 以实操示例展示了如何创建 SwiftUI Profiling 会话、按更新次数/耗时排序视图,并用因果图追踪更新来源。
排查症状之外,更应理解 SwiftUI 的刷新原理,才能从源头减少无效重绘。在我的文章理解 SwiftUI 的视图刷新机制:从 TimelineView 刷新问题谈起中,借由 TimelineView 个案系统阐述了视图声明、响应机制与递归更新的判定逻辑。只有搞清“为什么视图会更新”、“系统如何决定是否重算视图声明值”,优化才不会沦为补丁式修修补补。
工具
imessage-kit:在 AI Agent 中提供消息集成能力
imessage-kit 是一个由 Photon 开发的功能强大的 iMessage 开源 SDK,非常适合将 iMessage 集成到 AI 智能体或自动化工作流中。其主要功能有:
现代化的 API:提供优雅的链式调用(Fluent API),可以轻松实现“收到消息 A,则回复 B”的逻辑。
功能全面:不仅支持收发文本,还能处理图片、各类文件,并能实时监控新消息。
类型安全与跨运行时:完全使用 TypeScript 编写,类型支持良好,并同时兼容 Node.js 和 Bun。
AI 集成友好:官方定位就是为 AI Agent 提供消息集成能力,是连接物理世界和 AI 的一个有趣尝试。
它通过直接读取 iMessage 数据库(chat.db)并结合 AppleScript 实现自动化,因此仅限 macOS 使用,且需要授予应用”完全磁盘访问权限”。
该库采用 SSPL-1.0 许可证,禁止用于创建竞争产品(如其他消息 SDK/API),但允许用于内部业务、个人项目和教育用途。值得注意的是,Photon 还提供高级版本,支持线程回复、消息撤回/编辑、实时输入指示器等功能,以及企业级托管服务。更多内容可以在其官网获取。
SwiftUI-DetectGestureUtil:为单个 SwiftUI 视图绑定多个自定义手势
在 SwiftUI 中,让同一个视图同时识别多个手势一直是个棘手的问题。由 Saw-000 开发的 SwiftUI-DetectGestureUtil 通过引入独立的“检测阶段”,让开发者能在多个自定义手势中只确认其中一个,从而绕开系统默认组合方式(simultaneous、sequenced、exclusive)带来的约束,实现更自然的多手势交互。
它将手势识别流程清晰地拆分为两个阶段:
检测阶段(
detectGesture):在手势发生的整个周期内持续更新状态,直到某一自定义规则匹配并返回手势类型处理阶段(
handleGesture):在识别完成后持续追踪手势进展,通过.yet与.finished明确控制生命周期
这一模型为构建复杂交互(如“双击 + 拖动”、“圆形绘制”、“自定义笔迹检测”)提供了新的思路。借助 DetectGestureState,开发者可在一次手势周期内获得所有触点、时间与几何信息,实现远超 SwiftUI 原生 Gesture API 的表达力与精度。


