SwiftUI 新特性
What's new in SwiftUI
2025年6月9日
一句话判断
SwiftUI 这次最值得关注的不是 Liquid Glass 的视觉变化,而是 TextEditor 终于支持了 AttributedString——用纯 SwiftUI 构建富文本编辑器第一次成为现实。
这场 Session 讲了什么
SwiftUI 这次更新覆盖面很广,但如果你只记一件事,记住这个:过去五年里,任何需要富文本编辑的 SwiftUI 应用都不得不桥接 UITextView,写一堆 UIViewRepresentable 样板代码。现在 TextEditor 原生支持 AttributedString、选区管理和查找导航,这条桥接层终于可以拆了。
Liquid Glass 是另一个大变化,但对大多数开发者来说,它的影响是被动的——你不需要主动做什么,系统控件会自动采用新外观。真正需要你动手的是:检查你过去为 TabBar、Toolbar 写的自定义背景和模糊效果,它们大概率会和 Liquid Glass 冲突。glassEffect() 修饰符和 .glass 按钮样式是给那些需要自定义玻璃效果的人准备的。
其他值得注意的:@Animatable 宏消灭了手动实现 Animatable 协议的样板代码,visionOS 的 manipulable() 手势让 3D 交互不再是少数人的专属。
值得深挖的点
TextEditor 的富文本支持:为什么等了这么久
SwiftUI 从 2019 年发布至今,TextEditor 一直是纯文本工具。这不是 Apple 忘了——富文本编辑是一个极其复杂的问题域。选区管理、撤销栈、输入法交互、格式继承、大文档性能……每一个都是坑。Apple 选择在这个时间点放出原生支持,说明他们终于认为这些问题的解决方案成熟了。
新的 API 设计值得细看。AttributedTextSelection 不只是暴露选区范围,它把选区状态变成了 SwiftUI 的一等公民——你可以用 @State 管理它,这意味着选区变化天然遵循 SwiftUI 的声明式范式。AttributedTextFormattingDefinition 允许你定义”在代码块里自动用等宽字体,在引用块里自动用斜体”这类上下文敏感的格式规则。FindContext 把查找导航器内置到了编辑器里。
和旧方案对比:用 UITextView 包装时,你需要处理 updateUIView 的生命周期、协调 SwiftUI 状态和 UIKit 命令式 API、处理键盘避免逻辑……现在这些都不需要了。但有一个 trade-off:新 API 的灵活性可能不如直接操作 UITextView——如果你需要高度定制的文本布局或非标准输入法交互,UIKit 桥接可能仍然是唯一选择。
@Animatable 宏:编译器替你写代码
手动实现 Animatable 协议的痛点不是难度,是繁琐。每个可动画属性都需要写 animatableData 的 getter/setter,多个属性需要打包成 AnimatablePair,类型转换需要手动处理。@Animatable 宏用编译器魔法取代了这一切。
这不仅仅是语法糖。它降低了自定义动画的认知门槛——过去你需要理解 VectorArithmetic 协议才能做自定义过渡,现在只需要在结构体上加一个宏。但要注意:@Animatable 只适用于你的自定义 View 类型中的存储属性,系统类型(如 CGFloat、Color)本身已经支持动画,不需要也不能用这个宏。
代码片段
Liquid Glass 效果:让自定义视图融入系统新设计语言。
struct GlassCard: View {
var body: some View {
VStack {
Text("Hello, Liquid Glass")
.font(.title)
Button("Tap Me") { }
.buttonStyle(.glass)
}
.padding()
.glassEffect(.regular.interactive, in: .rect(cornerRadius: 20))
}
}
// 坑:glassEffect 的 shape 参数决定裁剪边界,
// 圆角半径不对会导致边缘出现不自然的硬切
@Animatable 宏:一行代码替代过去 20 行的 Animatable 协议实现。
@Animatable
struct PulseRing: View {
var scale: CGFloat // 自动获得动画能力
var body: some View {
Circle()
.stroke(.blue, lineWidth: 3)
.scaleEffect(scale)
}
}
// 坑:如果属性类型不支持 VectorArithmetic,编译器会报错,
// 但错误信息不一定能直接告诉你哪个属性有问题
富文本编辑器:纯 SwiftUI 实现,不再需要 UITextView 桥接。
struct RichTextEditor: View {
@State private var text = AttributedString("开始编辑...")
@State private var findContext = FindContext()
@State private var selection = AttributedTextSelection()
var body: some View {
TextEditor(text: $text, selection: $selection)
.findNavigator(isPresented: .constant(true), context: findContext)
.attributedTextFormattingDefinition(.inline)
}
}
// 坑:超长文档(>10000 字)的性能还需要实际验证,
// AttributedString 的 Copy-on-Write 在频繁编辑时可能产生意外的内存拷贝
最佳实践
已有项目:不要急着迁移。Liquid Glass 对系统控件是自动生效的,先编译看效果。如果过去给 TabBar、Toolbar 设置了自定义背景色或模糊效果,准备好花半天时间清理——它们大概率会和 Liquid Glass 冲突。TextEditor 的富文本支持值得评估,但现有的 UITextView 包装运行良好的话,没有理由立刻重写。
新项目:直接用新 API。TextEditor + AttributedString 比 UITextView 包装简单一个数量级。@Animatable 宏在任何需要自定义动画的场景下都值得用。
visionOS 开发者:manipulable() 手势是真正的生产力提升,但要注意和系统手势(捏合、旋转)的冲突。
还有什么值得关注
WebView+WebPage组合替代了WKWebView包装方案,app 内嵌网页的场景值得看看scrollEdgeEffectStyle()为滚动视图带来边缘视觉效果,和 Liquid Glass 配合效果很好ToolbarSpacer解决了玻璃工具栏项之间的视觉间距问题