Highlight
SwiftUI 这次更新覆盖面很广,但如果你只记一件事,记住这个:过去五年里,任何需要富文本编辑的 SwiftUI 应用都不得不桥接
UITextView,写一堆UIViewRepresentable样板代码。现在TextEditor原生支持AttributedString、选区管理和查找导航,这条桥接层终于可以拆了。
核心内容
写一个支持加粗、斜体、颜色高亮的备忘录类应用,过去在 SwiftUI 里有多痛?答案是:你得放弃 SwiftUI 的 TextEditor,改用 UIViewRepresentable 包一层 UITextView,自己处理选区同步、键盘工具栏、撤销栈,再用 NSAttributedString 与 SwiftUI 的状态对接。一个看似简单的功能,往往要写两三百行胶水代码。WWDC25 的 SwiftUI 把这条路彻底拉直:TextEditor 现在直接接受 AttributedString 绑定,选区管理也升级为一等公民。
Liquid Glass 是同一场更新里另一条主线。它的影响范围覆盖整个视觉系统,远超单个 API 的边界。系统自带的 TabBar、Toolbar、按钮在新 SDK 下会自动获得新外观;但任何过去手写的玻璃模糊、自定义背景色、ZStack 叠加都可能与新材质冲突。Apple 给了 glassEffect() 修饰符让自定义视图也能加入这套材质语言,同时新增了 ToolbarSpacer 用来分组工具栏按钮。再加上 @Animatable 宏自动合成 Animatable 协议、visionOS 上 manipulable() 让任意 3D 视图获得手部抓取与缩放——这是一次面向 iOS、iPadOS、macOS、visionOS 全平台同步推进的更新。
详细内容
工具栏分组与 Liquid Glass 按钮。新增的 ToolbarSpacer 用来在工具栏里把按钮拆成多个独立组,配合 Liquid Glass 后每一组会形成独立胶囊外观。
import SwiftUI
struct TripDetailView: View {
var body: some View {
NavigationStack {
TripList()
.toolbar {
ToolbarItemGroup(placement: .primaryAction) {
UpButton()
DownButton()
}
ToolbarSpacer(.fixed, placement: .primaryAction)
ToolbarItem(placement: .primaryAction) {
SettingsButton()
}
}
}
}
}
关键点:
ToolbarItemGroup把上下两个箭头按钮放进一个胶囊里,视觉上属于同一组。ToolbarSpacer(.fixed, placement: .primaryAction)在它们之后插入一个固定间隔;Liquid Glass 会据此把后面的按钮渲染成独立胶囊。SettingsButton因此从前两个按钮中分离出来,避免一切操作都挤在同一颗药丸上。
给自定义视图加玻璃材质。系统控件自动适配 Liquid Glass,但自己画的浮动按钮、提示卡需要主动声明。
import SwiftUI
struct ToTopButton: View {
var body: some View {
Button("To Top", systemImage: "chevron.up") {
scrollToTop()
}
.padding()
.glassEffect()
}
func scrollToTop() {
// Scroll to top of view
}
}
关键点:
.glassEffect()是新的视图修饰符,把所在视图渲染成 Liquid Glass 材质。- 它替代了过去
.background(.ultraThinMaterial)+.clipShape(Capsule())那一套手写组合。 padding()在前,让玻璃区域包含按钮内边距而不是仅紧贴文字。
@Animatable 宏消灭样板代码。过去给自定义 Shape 做动画,要手写 animatableData 并把多个属性塞进 AnimatablePair 嵌套。现在一个宏就够了。
import SwiftUI
@Animatable
struct LoadingArc: Shape {
var center: CGPoint
var radius: CGFloat
var startAngle: Angle
var endAngle: Angle
@AnimatableIgnored var drawPathClockwise: Bool
func path(in rect: CGRect) -> Path {
// Creates a `Path` arc using properties
return Path()
}
}
关键点:
@Animatable加在Shape上,编译期自动合成animatableData,把所有可插值属性串起来。@AnimatableIgnored标记不参与动画的属性——Bool这类离散值无法插值,必须排除。- 改一行代码,等价于过去十几行
AnimatablePair<AnimatablePair<…>, …>的样板。
visionOS:让 3D 视图可以抓、可以放在桌子上。manipulable() 让用户用手势抓取、旋转、缩放视图;surfaceSnappingInfo 让你知道视图是否吸附到了真实平面。
import ARKit
import RealityKit
import SwiftUI
struct BackpackWaterBottle: View {
@Environment(\.surfaceSnappingInfo) var snappingInfo: SurfaceSnappingInfo
var body: some View {
VStackLayout().depthAlignment(.center) {
waterBottleView
.manipulable()
Pedestal()
.opacity(
snappingInfo.classification == .table ? 1.0 : 0.0)
}
}
var waterBottleView: some View {
Model3D(named: "waterBottle")
}
}
关键点:
.manipulable()一行让Model3D视图获得抓取、旋转、缩放等系统手势。@Environment(\.surfaceSnappingInfo)读取当前吸附信息——分类有.table、.wall、.floor等。- 当用户把水瓶放到桌面时,下方的
Pedestal(底座)才显示出来;空中悬浮时则隐藏,视觉上更合理。
核心启发
-
做什么:把项目里所有
UIViewRepresentable<UITextView>的富文本桥接代码替换为原生TextEditor+AttributedString。- 为什么值得做:每个桥接层平均两三百行胶水代码,含选区同步、键盘工具栏、撤销栈三处易错点;原生 API 把这部分收回 SwiftUI,长期维护成本骤降。
- 怎么开始:先列出仓库里所有
UIViewRepresentable子类,挑选只用到加粗/斜体/颜色这种基本属性的最小场景试点,再逐步迁移复杂场景。
-
做什么:盘点工具栏自定义背景,迁移到
ToolbarSpacer+ Liquid Glass 默认外观。- 为什么值得做:过去为了视觉对齐而设的
.toolbarBackground自定义颜色,在 Liquid Glass 下会破坏新材质的折射效果,编译后大概率丑。 - 怎么开始:用 Xcode 全文搜索
toolbarBackground、ultraThinMaterial,逐一去掉自定义、用ToolbarSpacer(.fixed, ...)重新分组按钮,再视觉回归。
- 为什么值得做:过去为了视觉对齐而设的
-
做什么:把所有手写
animatableData的Shape改成@Animatable宏。- 为什么值得做:手写
AnimatablePair嵌套是高度模板化的代码,改一个属性就要改三处;宏从源头消除这种低价值劳动。 - 怎么开始:搜索
var animatableData关键字定位所有候选,逐个加上@Animatable,对离散属性补@AnimatableIgnored,跑一遍 UI 测试确认动画曲线一致。
- 为什么值得做:手写
-
做什么:在 visionOS 项目里给所有
Model3D视图加manipulable()评估。- 为什么值得做:用户在空间环境里第一反应就是用手抓东西,过去要自己写
DragGesture+RotateGesture3D组合;现在一行修饰符替代。 - 怎么开始:先在演示场景里挂上
.manipulable(),再用surfaceSnappingInfo读吸附状态,决定吸附后是否显示底座、阴影等辅助视觉。
- 为什么值得做:用户在空间环境里第一反应就是用手抓东西,过去要自己写
关联 Session
- Meet Liquid Glass — Liquid Glass 设计语言总览,先看这一篇再读 SwiftUI 的实现。
- Build a SwiftUI app with the new design — 用一个完整应用串起 Liquid Glass 在 SwiftUI 里的落地流程。
- Cook up a rich text experience in SwiftUI with AttributedString —
TextEditor+AttributedString富文本编辑的代码协同。 - Explore concurrency in SwiftUI — SwiftUI 与 Swift 并发的交互模型,新更新背后的执行模型。
- Optimize SwiftUI performance with Instruments — 新增的 SwiftUI Instrument,配合本场更新做性能验证。
评论
GitHub Issues · utterances