7 年前苹果在 2019 年 WWDC 的压轴环节正式向外界公布了全新的 UI 框架 SwiftUI。这是一个姗姗来迟的产品——相比 Google 的 FlutterSwiftUI 足足晚了两年亮相。但苹果依然选择将它放在当年 WWDC 的最后重磅发布足以看出这套新框架在苹果内部的重要地位。对于开发者而言SwiftUI 为 iOS、macOS、watchOS、tvOS 等设备提供了一套统一的 UI 框架它曾经承载着一个非常美好的愿景未来开发 Apple 生态应用将不再需要面对不同平台间割裂的开发体验。当时无数人翘首以盼期待这会成为苹果下一代应用开发的基石。但 7 年过去曾经的期待如今还剩下多少来自一位开发者 Yakov Manshin 的评价或许代表了不少开发者的真实感受“到了 2026 年SwiftUI 依然给许多开发者一种‘长期测试版’的感觉。”这句话迅速引发了开发者社区的共鸣。在他发表的《SwiftUI After 7 Years: A Story of Mediocrity》一文中Yakov Manshin 回顾了 SwiftUI 七年来的发展历程并试图回答一个问题为什么一个曾经让开发者充满期待的框架最终却逐渐成为许多资深工程师眼中的失望之作接下来他将拆解苹果的 SwiftUI 在性能、布局可预测性等方面长期存在的问题梳理其数据流设计不断变化带来的混乱以及令人头疼的向后兼容问题——这些问题迫使开发者不得不依赖大量适配层和临时方案才能让项目继续稳定运行。通过真实案例包括苹果官方 SwiftUI 教程自身暴露的问题以及 SwiftUI 与 UIKit 的性能正面对比下文也试图展示SwiftUI 看似带来了更简单、更现代的开发体验但这种简化背后也意味着开发者逐渐失去了对应用行为的精准控制。而这篇文章讨论的其实并不只是一个 UI 框架的问题。在更深层次上它也折射出苹果软件开发文化的变化——从早期 Cocoa、Aqua 和 Auto Layout 时代对产品工艺、细节打磨近乎苛刻的追求到如今更加倾向于“够用就行”的现代企业文化。如果你已经厌倦了不断为 SwiftUI 的缺陷寻找解释反复与布局 Bug 斗争或者一次次替苹果完成本该由他们承担的质量验证工作那么这篇文章或许值得一读。来源https://ykvm.com/2026/07/swiftui-a-story-of-mediocrity/作者 | Yakov Manshin 责编 | 苏宓出品 | CSDNIDCSDNnewsSwiftUI 于 2019 年正式发布并引发了巨大的关注。我当时就在现场也亲眼见证了这一切。苹果当时承诺它将终结开发者与 Auto Layout 长期斗争的时代也不必因为一次微小的改动就反复重构整个应用。取而代之的是声明式语法、单一数据源、内置动画、即时预览以及代码在苹果全平台之间的复用能力。对我来说这听起来好得令人难以置信。事实证明确实如此。到了现在最初的兴奋感不仅已经消退甚至逐渐转变成一种越来越强烈的职业挫败感。而七年之后“SwiftUI 仍然只是一个年轻框架”这种说法已经站不住脚了。在这个行业里七年几乎等同于一个漫长时代。它大致相当于从这个版本到那个版本之间的时间跨度也超过了第一代 iPhone 发布到 iOS 7 重新设计之间的时间。相比之下SwiftUI 给人的感觉更像是一直处于测试阶段。每一个新功能背后都伴随着一堆隐藏在细则里的限制条件。每一次布局修复都可能导致两个你根本没有修改过的地方出现新的问题。说实话我已经厌倦了在自己的项目里不断为这些问题寻找借口。为什么 SwiftUI 会出现不过在我们深入了解 SwiftUI 的具体优势和缺陷之前我们先来看看 SwiftUI 为什么会出现。这并不完全是因为苹果想要为开发者提供更好的开发工具而是因为它某种程度上不得不这么做。苹果需要回应来自竞争对手的压力。到了 2010 年代中期Facebook 的 React 已经成为 Web 开发领域事实上的标准随后 React Native 和谷歌的 Flutter 也开始向移动平台发起进攻。这两个框架都采用了响应式和声明式的设计理念。从任何一家企业的角度来看继续开发原生应用开始显得越来越不划算。相比之下他们可以使用同一套代码库同时支持 iOS 和 Android并且还能复用自己网站上的组件。我认为还有另一个原因那就是 Mac App Store。你可以回忆一下上一次打开它是什么时候你上一次在 Mac 上安装一个新的原生应用又是什么时候没错我也是一样。iOS App Store 是苹果向服务业务转型过程中的关键一步原因在于它可以从每一笔交易中抽取 30% 的分成。但在 Mac 平台上许多应用要么只能通过浏览器使用要么只是基于 Electron 封装的 Web 应用。SwiftUI 原本被寄予厚望希望同时解决这两个问题一方面让开发者继续留在原生生态中构建新的应用另一方面让已有应用更容易迁移到 Mac 平台。响应式数据流、声明式布局以及跨平台支持是 SwiftUI 最核心的卖点。那么苹果是否兑现了这些承诺让我们继续深入看看。数据流一直困扰着资深工程师包括我自己的一大痛点就是数据流问题。理论上“单一数据源”听起来像是一个完美的设计理念。但在实际使用中它却变成了一团由属性包装器、宏以及不断变化的配套框架组成的混乱系统。最开始我们使用的是 State、Binding 和 ObservedObject。随后苹果意识到这种方式的性能表现非常糟糕SwiftUI 会不断重新渲染视图。于是它推出了 Observation 框架以及 Observable 宏。苹果试图通过编译器层面的技巧来解决这个问题但显然这还远远不够因此布局引擎依旧像是在不断猜测。在 SwiftUI 中你永远无法确定一个视图到底会更新多少次以及它为什么会选择在某个时刻进行更新。即使使用那些没有公开文档的调试 API也无法获得完整的信息。SwiftUI 的数据流确实是响应式的——但有时候我甚至希望它不要这么响应因为它经常以错误的方式做出反应。它会响应那些本应该忽略的变化却忽略那些真正重要的变化。在我看来SwiftUI 的响应机制就像一个黑盒它让实现可预测的行为变得几乎不可能。布局系统这也引出了 SwiftUI 在架构层面的问题。接下来我们聊聊 SwiftUI 的布局系统。如果你曾经构建过任何复杂一点的界面那么你一定知道 SwiftUI 带来的挫败感。它的布局引擎极其不可预测。SwiftUI 建立在“尺寸协商”的理念之上。在发布会演示中这听起来非常合理但当你真正尝试构建一个浮动视图或者自定义侧边栏时它就会变成一场噩梦。说到自定义侧边栏苹果 SwiftUI 教程里的那个示例项目https://developer.apple.com/tutorials/swiftui/creating-a-macos-app使用的是一个非常标准、没有任何定制的侧边栏。你用最新版 Xcode 构建项目再用最新版 macOS 启动应用——结果却会看到这样的情况。我第一次注意到这个问题是在两年多以前而从那以后一切都没有改变。哦抱歉有一件事变了。由于 Liquid Glass 的加入现在按钮的尺寸也发生了变化——当然这个问题严格来说并不能算是 SwiftUI 的问题。但真正属于 SwiftUI 的问题是整个 UI 布局系统的脆弱性。它们会以最意想不到的方式、在最不合适的时刻崩溃。你可以在真正投入生产的应用中看到这种情况比如 UTM。它是一款非常出色的工程作品但由于大量依赖 SwiftUI有时候它给人的感觉更像是一个早期原型。最终你会发现自己不得不用 GeometryReader 包裹所有东西。而这其实就是一种彻底失败的表现。一旦使用了 GeometryReader你就已经失去了 SwiftUI 最核心的声明式优势。现在你必须手动计算坐标而且代码量甚至比 Auto Layout 还要复杂——这本身就非常讽刺。更糟糕的是仅仅因为 SwiftUI 的布局系统又发生了一次变化你可能下一次更新时就不得不重新编写所有坐标计算逻辑。API 稳定性与功能完整性接下来我们聊聊 API 稳定性以及功能完整性——或者说SwiftUI 在这方面的欠缺。如果你查看任何一个现代 SwiftUI 项目的代码库你都会发现里面充斥着大量 if #available 判断多到几乎令人觉得滑稽——实际上却令人尴尬。2019 年的时候有人还在畅谈“写更少的代码写更好的代码”。那么七年过去之后我们得到的是什么比如说你希望像从 iOS 7 时代开始那样在用户滚动页面时隐藏键盘。抱歉在 SwiftUI 中实现这个功能你需要 iOS 16。也许你也想让用户自定义窗口工具栏就像他们从 2001 年大概是那个时候开始就可以做到的事情一样。而 SwiftUI 直到几年前才终于获得了这个所谓的“突破性”功能。然后还有一个最基础的任务显示你从网络获取的图片。不过你最好自己写一个图片加载器因为 AsyncImage 直到 iOS 15 才被引入。但如果你还希望对这些图片进行缓存我有一个坏消息告诉你你根本做不到。因为直到现在2026 年 7 月这个 API 依然处于测试阶段。对于这些场景开发者通常只能自己创造各种变通方案和临时解决办法。而当苹果最终提供那些早在 AppKit 或 UIKit 中存在了几十年的 API 时你却不得不同时维护多套实现。但即使你使用的 API 是 SwiftUI 第一版就已经提供的也很有可能它后来被重新命名或者被一个功能相近的新 API 替代。一个典型例子就是 NavigationView。它一直以来都以 Bug 众多而闻名。看起来苹果并没有选择修复它而是决定直接用 NavigationStack 替换整个组件。但这又意味着你必须同时维护两套代码分支一套支持新系统一套兼容旧版本。所以这到底算是“更少的代码”还是“更好的代码”你来告诉我吧因为我自己也有点搞不清楚。这种持续不断的 API 更替最终导致了开发地狱。我们本应该只需要声明一次 UI 结构但实际上我们不得不为兼容性编写各种适配层和补丁然后祈祷它们不会在下一次系统更新中崩溃。某种意义上我们实际上是在替苹果完成它应该做的质量测试工作。这些问题本应该在 2019 年解决——好吧至少应该在 2020 年解决。然而七年过去了SwiftUI 依然没有实现与那些所谓“遗留”框架相同的功能完整性。SwiftUI 就像是在原地打转而我们只能跟着它一起跑才能勉强停留在原来的位置。但你知道吗如果苹果没有假装 SwiftUI 已经足够稳定并且可以作为未来几十年的基础这些问题其实都不会成为如此严重的问题。如果你可以直接调用最新 API 编写代码然后将它回溯部署到旧版本 iOS 上这些问题也不会存在。是的你仍然需要更频繁地重构代码逐步淘汰旧实现。但至少当前版本的代码可以在所有设备上保持一致运行。这也是 Android 现代 UI 框架采用的方式。Jetpack Compose 本质上只是一个通过依赖管理器获取和更新的软件包。之后它会直接被打包进你的应用程序中并且可以运行在最早 2014 年左右的设备上——同时还能提供完全一致的 UI 表现。性能接下来我们聊聊性能。这是一个无法掩盖的问题——即使苹果仍然试图通过只展示 SwiftUI 在最新硬件上的运行效果来淡化它。但事实是无论苹果多少次承诺会改进SwiftUI 的性能依然没有达到应有的标准。它并不像一个运行在“高端平台”上的“第一方核心框架”应该有的表现。比如这是我自己做的 UIKit 与 SwiftUI 的正面对比测试。测试内容非常简单一个图片画廊来自我之前版本的 Playground 应用。为什么是之前版本因为后来我已经使用终极跨平台框架重新构建了整个应用。不过那是另一个故事了。回到测试本身。即使采用了各种性能优化手段比如在后台线程解码图片SwiftUI 网格视图的滚动体验依然明显不够流畅。更不用说如果你必须记住一些晦涩难懂的优化技巧才能让它正常运行那么 SwiftUI 最初承诺的简单性就已经荡然无存了。这只是我进行的多个测试中的一个而且我特意选择了一台较旧的 iPhone。但其实这不应该成为借口。因为如果你需要一颗 M5 Pro Max 级别的超级芯片才能流畅展示一堆 JPEG 图片那说明你的整个架构存在严重问题。高质量软件不应该这样构建它本来就不应该以这种方式工作。跨平台神话这就引出了 SwiftUI 最后的一个承诺——跨平台支持。我看过几场早期的 SwiftUI 发布会。公平地说我并没有在其中任何一场听到“一次编写随处运行”write once, run anywhere这样的说法。苹果通常使用的表述是“学习这些工具一次然后将它们应用到所有平台。”但这里存在一个问题。你在 iOS 上学到的 SwiftUI 知识很少能够直接应用到 Mac 上的布局开发中。除非你最终想做出那种看起来格格不入的 UI——就像苹果把 iPad 应用带到 Mac 上之后的那些应用一样。SwiftUI 的核心概念比如数据流和组合式布局在不同平台之间大致是一致的。但你实际使用的具体组件以及配置这些组件的方式往往完全不同。更不用说同一个视图组件在不同平台上的实现方式也可能存在差异。换句话说为一个 6 英寸手机设计 UI和为一台 27 英寸桌面电脑设计 UI本来就不是一回事。谁能想到呢根据我的经验SwiftUI 所谓的“学一次到处应用”经常会变成“学一次学两遍到处应用处处调试。”当然前提是你希望构建出真正符合平台习惯、看起来专业的 UI。如果你不在意这一点那么 SwiftUI 确实可以给你带来一些“能用”的结果或者“差不多”的结果。理念上的转变事实上我认为这种“差不多就行”的心态才是这里最大的问题。我认为它代表了苹果整个软件开发理念的一次重大转变。随着 SwiftUI 的出现我们进入了一个这样的时代一个“大部分情况下能工作”的东西就被认为已经足够。或者说一个只覆盖 90% 使用场景的产品也可以被认为是成功的。过去对于生产级质量和稳定性的要求正在让位于所谓的“速度”。而“速度”这个词通常是在你想要更快地发布垃圾产品时才会使用的。在 Cocoa 时代这是无法想象的。在 Mac OS X 的早期阶段这种情况甚至会是一场灾难。你能想象一个 SwiftUI 版本的经典 Aqua 发布会吗想象一下如果当年乔布斯没有展示那些看起来如此精美、甚至“让人想舔一下”的液态按钮而是展示闪烁的侧边栏和不断跳动的按钮。他恐怕会被彻底嘲笑。但现在似乎我们正在接受“够用”的产品以及“差不多就行”的心态。这种对于工艺品质的标准我无法接受。而且这并不只是某一个框架的问题。这是一次系统性的变化。最开始一家公司提出“快速行动打破常规”的理念。渐渐地越来越多开发者加入其中。他们并不一定真的都在快速行动但发布存在缺陷的产品开始变得正常起来——甚至连第一方应用和系统组件也不例外。比如Apple Music 多年来一直存在一个 Bug编辑播放队列时歌曲列表会突然跳动然后播放完全错误的歌曲。TestFlight 会裁剪截图选择区域而且没有任何边距。iPad 上的设置应用会显示各种崩溃报告。主屏幕会显示同一个应用的重复图标状态栏会来回跳动它还会显示一些本不应该出现的图标轮廓。甚至像 Logic Pro 这样的专业应用如今也会带着缺失的本地化内容发布。你知道的就是那些本应该成为质量和稳定性标杆的专业应用。我可以继续列举很多例子。虽然这些问题并不全部都使用 SwiftUI但它们反映出了苹果如今认为“可以接受”的质量标准。我并没有费很大力气去寻找这些问题它们只是我过去几个月里亲眼遇到的事情。所以考虑到这些例子后旗舰级系统框架让开发者几乎无法构建一个完全没有问题的应用也就不足为奇了。尤其是在苹果平台上这种变化大约始于 2018 年也就是我前面提到的那些“格格不入”的应用出现的时候。那时Project Marzipan后来更名为 Catalyst首次允许开发者将 UIKit 代码复用于 Mac 平台。科技媒体纷纷批评这些应用的表现。但苹果并没有选择重新打磨这些基础工作反而进一步强化了跨平台开发的理念并推出了 SwiftUI。而这个全新的、未经充分验证的框架又带来了更多性能、稳定性以及视觉体验方面的问题。我的结论是降低质量标准是一种选择而不是迫不得已的结果。我拒绝接受这种选择。这也是为什么即使过去七年SwiftUI 依然无法让我完全信任。总结最后回到开头提出的问题SwiftUI 到底出了什么问题如果把它存在七年时间里那些始终没有解决的问题全部考虑进去答案就是一切。或者至少是构建稳定、高性能、可维护系统时最重要的那些部分。SwiftUI 的故事是一个关于平庸化和标准降低的故事。我们被要求用可预测的精确性去交换一种虚假的便利。然后我们被迫在两种选择之间做决定要么花大量时间调试框架本身要么就这样发布一个存在问题的应用。作为一名资深工程师我对这两个选择都没有兴趣。我无法认同“差不多能用就行”的心态我认为用户值得拥有比“足够好”更好的产品。SwiftUI 并不是一个真正糟糕的框架。它只是平庸。而在我看来这反而糟糕得多。所以至少目前我依然更倾向于使用那些“遗留”的 UI 框架。后记多年来我一直在观察 SwiftUI 努力成为 AppKit 和 UIKit 的可靠替代品——换句话说成为苹果早在 2019 年承诺它会成为的那个样子。这些年来我不断测试 SwiftUI 的每一次新版本希望那些长期困扰它的问题最终能够得到解决。但随着时间推移SwiftUI 并没有在根本上变得更好。它依然像七年前一样不够成熟而使用 SwiftUI 构建的应用大多数也依然表现得平淡无奇。但我观察的不只是 SwiftUI 的困境。我也一直在观察那些真心认为“只要一个 SwiftUI 功能现在能正常工作那自己的任务就完成了”的软件工程师。除非他们是故意选择了更差的工具否则我其实并不完全责怪他们。好吧也许还是有一点。因为你无法忽视长期维护成本而不为此付出代价。不过通常情况下真正承担这个代价的并不是这些工程师个人而是他们所在的公司。但在如今这个企业热衷于用 AI Agent 替代人类的时代很难期待这些企业生产出的产品质量会有所提升。而这些企业往往也是那些把软件开发视为一种商品化流程或者线性生产过程的公司。他们通常追求的是“快速交付”而不是“正确交付”。我们已经开始看到这种做法带来的结果而未来还会看到更多。