WWDC Quick Look 💓 By SwiftGGTeam
What’s new in visionOS 26

What’s new in visionOS 26

观看原视频

Highlight

visionOS 26 把 volume 提升为一等公民:可以弹 sheet、可以溢出边界、可以让 3D 物体跟随手势旋转,且只需一个 view modifier。


核心内容

去年 Vision Pro 上市以来,开发者最常踩的坑是:volume 像一个”封闭盒子”。容器内的 3D 内容能渲染,但 alert、sheet、menu 这些日常 UI 在 volume 里没法用,超出窗口边界的几何会被裁掉,3D 物体的旋转手势要自己写一整套。结果是每个 volumetric app 都在重复造轮子,体验还参差不齐。

visionOS 26 把这些痛点逐一拆掉。Edwin 在开场就点明思路:让 SwiftUI 既有的 2D 布局工具自然延伸到 3D。depthAlignmentVStack 能沿前后轴对齐,rotation3DLayout 把旋转纳入布局系统,preferredWindowClippingMargins 允许内容溢出边界,Object Manipulation API 用一个 .manipulable() 修饰符替掉自定义手势栈。系统还把 SwiftUI、RealityKit、ARKit 三套坐标系打通,写 RealityKit 的人不再需要绕 RealityView 中转,可以直接给 entity 挂 SwiftUI 手势和 attachment。这些改动加在一起,volume 才真正可以承担起完整的 app 主场景。

详细内容

SwiftUI 布局走入第三维(02:25

// Layout types back align views by default

struct LandmarkProfile: View {

    var body: some View {
       VStackLayout().depthAlignment(.front) {
            ResizableLandmarkModel()
            LandmarkNameCard()
        }
    }
}

关键点:

  • VStackLayout() 是熟悉的垂直栈,过去只在 X/Y 平面工作。
  • .depthAlignment(.front) 把所有子视图沿 Z 轴对齐到同一个前平面;3D 模型可以更深,名片自动贴到模型最前面,可读性显著提升。
  • 这是布局级修饰符,不需要手工算 offset。

Volume 中的内容溢出(04:22

// Dynamic Bounds Restrictions

struct ContentView: View, Animatable {

    var body: some View {
        VStackLayout().depthAlignment(.front) {
            // . . .
        }
        .preferredWindowClippingMargins(.all, 400)
    }
}

关键点:

  • preferredWindowClippingMargins(.all, 400) 告诉系统:允许内容向四周各方向溢出 400 点。
  • 用途是让虚拟物体”探出”窗口,例如山峰冒出 volume、瀑布越过边界,无需为此把 volume 尺寸调大。
  • 这是偏好(preferred),系统会在需要时按距离与遮挡情况自行裁剪。

Object Manipulation:一个 modifier 搞定(05:05

// Apply the manipulable view modifier to each Model3D block per 3D object

struct RockView: View {
    var body: some View {
        RockLayout {
            ForEach(rocks) { rock in
                Model3D(named: rock.name, bundle: realityKitContentBundle) {
                    model in
                    model.model?
                        .resizable()
                        .scaledToFit3D()
                }
                .manipulable()
            }
        }
    }
}

关键点:

  • .manipulable()Model3D 自动支持双手抓取、旋转、缩放,与现实物体一致的物理直觉。
  • 不需要写 DragGesture + RotateGesture3D 的组合,也不需要手动处理两手协同。
  • 用 RealityKit 的同学走 ManipulationComponent.configureEntity(rock) 即可获得相同行为;用 Quick Look 预览的 USDZ 模型则免费获得该能力。

SwiftUI 手势直接挂到 Entity(06:36

// Gestures on entities
struct GestureExample: View {
    @GestureState private var dragMountain: Float = 0
    @GestureState private var dragTerrain: Float = 0
		var body: some View {
        RealityView { content in
            let drag1 = GestureComponent(
                DragGesture().updating($dragMountain) { value, offset, _ in
                    offset = Float(value.translation.width)
                })
            let drag2 = GestureComponent(
                DragGesture().updating($dragTerrain) {evalue, offset, _ in
                    offset = Float(value.translation.width)
                })
            mountain.components.set(drag1)
            terrain.components.set(drag2)
        } update: { content in
            // . . .
        }
    }
}

关键点:

  • GestureComponent 把 SwiftUI 的 DragGesture 直接装到 entity 上,不再需要 RealityView 当中介转发命中测试。
  • 每个 entity 可以挂自己独立的手势,互不干扰;以前要写一长串 targetedToEntity 分支判断。
  • @GestureState 仍然走 SwiftUI 的状态管理,过去的写法可以平移过来。

Look to Scroll:抬眼即滚动(33:45

// SwiftUI
var body: some View {
    ScrollView {
        HikeDetails()
    }
    .scrollInputBehavior(.enabled, for: .look)
}


// UIKit
let scrollView: UIScrollView = {
    let scroll = UIScrollView()
    scroll.lookToScrollAxes = .vertical
    return scroll
}()

关键点:

  • 在 SwiftUI 中加一行 scrollInputBehavior(.enabled, for: .look),用户视线移到边缘即可触发滚动,无需腾出手。
  • UIKit 路线用 lookToScrollAxes,按需指定垂直、水平或两者。
  • 阅读类、长内容浏览类 app 是首批受益者;游戏类要谨慎,避免与瞄准操作冲突。

其他重点更新

  • Foundation Models 框架(10:53):访问设备端 LLM,支持 guided generation 与 tool calling。
  • Spatial Audio Experience API(08:26):每个 window/volume 各自空间化音源,可在 scene 间无缝迁移。
  • Environment Occlusion(09:04):通过 EnvironmentBlendingComponent 让虚拟物被真实静态物体遮挡。
  • Nearby Window Sharing 与共享 ARKit world anchors:同房间多人对同一个 volume 操作;老的 SharePlay 代码无需改动即可获得 nearby 体验,加 isNearbyWithParticipant 检查可做更精细的差异化。
  • Spatial Browsing 与 HTML <model>:网页里直接放 USDZ 模型,浏览长文进入空间化阅读模式。
  • 企业 API:Protected Content 一个 modifier 禁截屏/录屏/AirPlay;Window Follow Mode 让窗口跟随用户走动;Return to Service 用于设备共享时的安全重置。

核心启发

  • 把 volume 当成主舞台,把 window 当成附庸:以前用 window 做主体、volume 装 3D 配件;visionOS 26 之后反过来更合理。volume 现在能弹 sheet、能溢出边界、能空间化音频,主交互完全可以放进去。

    • 为什么值得做:让 app 一开始就具备空间感,避免用户在二维窗口里感受不到 Vision Pro 的差异。
    • 怎么开始:把首屏 scene 改成 WindowGroup(.volumetric),加上 depthAlignment(.front) 排版主元素,再用 preferredWindowClippingMargins 让关键物体探出边界。
  • 删掉自己写的 3D 手势栈,全部换成 .manipulable() / ManipulationComponent:手势协同、双手缩放、惯性回弹这些细节苹果已经统一好了,自己实现很难达到系统级一致性。

    • 为什么值得做:用户在 Quick Look、系统照片、其他第三方 app 中已经形成一致的肌肉记忆,自定义手势会破坏这种心智。
    • 怎么开始:把现有的 DragGesture3D + RotateGesture3D 组合替换;RealityKit 端在 RealityView 的 make 阶段对每个可交互 entity 调一次 ManipulationComponent.configureEntity(_:)
  • 媒体类 app 优先支持 APMP(Apple Projected Media Profile):Canon、GoPro、Insta360 拍出的 180/360 度与广角素材现在有统一元数据,导入后可直接走系统沉浸式播放管线。

    • 为什么值得做:用户从外部相机导入越来越多素材,APMP 让你不必为每种镜头做特例处理。
    • 怎么开始:检查上传链路是否保留原始元数据;播放器端使用系统提供的沉浸式 player,让 projection 信息驱动渲染。
  • 企业内部 app 默认套上 Protected Content:金融、医疗、设计稿审阅这类视图,截屏与 AirPlay 是合规高风险点。

    • 为什么值得做:一个 view modifier 就能闭合一类合规问题,零业务逻辑改动。
    • 怎么开始:找到展示敏感数据的 view 根节点,加上 Protected Content modifier;对外部分享用例评估是否需要 Window Follow Mode 进一步约束。

关联 Session

评论

GitHub Issues · utterances