WWDC Quick Look 💓 By SwiftGGTeam
What's new in SwiftUI

What's new in SwiftUI

观看原视频

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 全文搜索 toolbarBackgroundultraThinMaterial,逐一去掉自定义、用 ToolbarSpacer(.fixed, ...) 重新分组按钮,再视觉回归。
  • 做什么:把所有手写 animatableDataShape 改成 @Animatable 宏。

    • 为什么值得做:手写 AnimatablePair 嵌套是高度模板化的代码,改一个属性就要改三处;宏从源头消除这种低价值劳动。
    • 怎么开始:搜索 var animatableData 关键字定位所有候选,逐个加上 @Animatable,对离散属性补 @AnimatableIgnored,跑一遍 UI 测试确认动画曲线一致。
  • 做什么:在 visionOS 项目里给所有 Model3D 视图加 manipulable() 评估。

    • 为什么值得做:用户在空间环境里第一反应就是用手抓东西,过去要自己写 DragGesture + RotateGesture3D 组合;现在一行修饰符替代。
    • 怎么开始:先在演示场景里挂上 .manipulable(),再用 surfaceSnappingInfo 读吸附状态,决定吸附后是否显示底座、阴影等辅助视觉。

关联 Session

评论

GitHub Issues · utterances