上周让 Claude 给我写个设置页。同一个需求,我先要了 React 版本:一次过,编译、运行、样式全都在线。再要 SwiftUI 版本:编译都没过。

模型不是菜——是 SwiftUI 这几年的路,实在是太野了。

1. 模型的记忆停在去年

SwiftUI 从 2019 年出生到现在,核心 API 大概换了三代:

  • 状态:BindableObject → ObservableObject + @Published → @Observable
  • 导航:NavigationView → NavigationStack / NavigationSplitView
  • 数据流的各种搭配,每年 WWDC 都有新姿势

训练语料里三代的代码全都有,而且按体积看,老代码还占大头。于是模型随手一抓就是 2019 和 2026 的写法混着来,NavigationView 套 @Observable,能编译才有鬼。

// 模型给你的
NavigationView { ... }  // 两年前就 deprecated 了
 
// 实际该写的
NavigationStack { ... }

对比一下 React:useState、useEffect 从 2019 用到今天纹丝不动,十年语料全是同一套 API。模型写 React 当然溜——不是它偏爱 Web,是 Web 不折腾。

2. 看不见的 UI

Web 调 UI,F12 一开,DOM 就在那,元素、层级、样式全可看可改。SwiftUI 的渲染树是个黑盒:你声明的和你看到的之间隔着一层运行时魔法,出了问题,agent 只能靠猜。

Preview 本该是救命稻草,实际是半个坑:Preview 崩溃的原因经常和真跑起来不一致,报错还能神奇地指到别的行。人都得烧香,何况模型。

3. Swift 6 的高墙

好不容易编译过了,Swift 6 的严格并发检查在后面等着。agent 顺手写的回调,动不动一个 @Sendable 报错把人拍醒。我自己 App 的后台队列回调就被 actor isolation 的断言坑过,排查了一下午。

严格并发是好事——对人是好事,对模型是条减速带:它语料里的 Swift 代码,一大半是不讲究并发的旧 Swift。

4. 尴尬到底在哪

所以 SwiftUI 的尴尬很清楚了:它是 Apple 最现代的框架,却是 agent 最写不好的框架。反过来,AppKit 三十年 API 稳如老狗,模型答 AppKit 的题又快又准。

AI 时代奖励什么样的 API?稳定、文本化、可 grep、错误尽量在编译期。SwiftUI 几乎全反着来:一年一变、声明式黑盒、错误运行时才炸。

但我不觉得 SwiftUI 要完。人盯着 Preview 把方向,agent 干体力活,其实是很搭的组合。尴尬的不是 SwiftUI 不好——是它一直在变,而模型的记忆,永远停在去年。