WWDC25

2025 年 6 月 30 日

SwiftUI 空間佈局大進化:從 2D 轉向 3D 空間開發的核心指南

已複製到剪貼板


迎接空間運算的新維度

對於長期深耕 Apple 生態系的開發者而言,過往的 UI 構建始於點(Points)與像素(Pixels)的平面座標。然而在 visionOS 的環境下,開發者正面臨一個核心挑戰:如何維持 SwiftUI 簡潔的宣告式語法,同時精準操控「幾何感知 Geometry-aware」的 3D 佈局?

WWDC 2025:Meet SwiftUI spatial layout
WWDC 2025:Meet SwiftUI spatial layout

Apple 在 visionOS 26 引入的空間佈局更新,並非只是簡單的 3D 渲染,而是一場佈局思維的範式轉移。透過將熟悉的 VStackHStack 擴展至 Z 軸,並引入具備座標空間同步能力的 API,SwiftUI 讓開發者能將重點從「手動計算空間位置」轉向「定義物件間的邏輯關係」。這不僅大幅簡化了開發工作流,更在系統層面確保了佈局、動畫與狀態管理在 3D 環境中的高度一致性。

深度 Depth:SwiftUI 佈局系統的第三個座標軸

在 visionOS 中,SwiftUI 正式將深度納入核心計算。除了寬度(Width)與高度(Height),系統現在會為每個視圖計算深度(Depth)與 Z 軸位置。

彈性深度與幾何表現

從架構角度看,visionOS 26 區分了「固定」與「彈性」的深度行為。例如,ImageText 預設為零深度。而 Model3D 的行為類似於 Image 的 3D 版本,具備固定的幾何尺寸。 然而,RealityViewGeometryReader3D 預設會佔據所有可用的深度建議(Proposed Depth),這種「彈性深度」特性讓它們在複雜場景中能自動填滿容器。

解決「太妃糖 Taffy」效應

當開發者對 Model3D 使用 resizable() 時,若視窗比例不符,模型會像太妃糖一樣被異常拉伸。為了解決這點,visionOS 26 引入了 scaledToFit3D

  • 關鍵機制:它確保模型在適應可用空間時,能同時維持寬、高、深的三維比例,而不是僅僅在 2D 平面進行縮放

根深度建議 Root Depth Proposal

系統根據容器類型提供不同的深度策略:

  • Window:提供固定的深度建議,超出範圍的內容會被裁切
  • Volume:深度是可調整的,這讓 3D 佈局能隨使用者縮放容器而動態重繪

深度對齊 Depth Alignment:精準掌控 Z 軸層次

當多個物件在 Z 軸堆疊時,depthAlignment 成為了關鍵的架構工具。這不僅是視覺位置的調整,更是「深度提案」在佈局鏈中的傳遞。

ZStack 的深度合成

正如 VStack 合成高度,ZStack 現在會合成其子視圖的深度。預設情況下,Stack 會使用 .back(後方)對齊。這解釋了為什麼在 VStack 中放置模型與標籤時,標籤往往會被模型遮擋。將對齊改為 .front,即可確保 UI 元素在視覺上始終處於模型前方。

自定義深度對齊:實作「深度頒獎台」

為了達成更複雜的層次感(例如將特定物件前移以示重要性),我們需要實作 DepthAlignmentID。以下是建立「深度頒獎台 Depth Podium」的實作邏輯:

// 1. 定義自定義對齊 ID
struct DepthPodiumAlignment: DepthAlignmentID {
    static func defaultValue(in context: ViewDimensions) -> CGFloat {
        context[.front] // 預設對齊最前端
    }
}

extension DepthAlignment {
    static let depthPodium = DepthAlignment(DepthPodiumAlignment.self)
}

// 2. 應用於佈局與 Guide
HStack(alignment: .center, depthAlignment: .depthPodium) {
    ResizableRobotView(model: "Robot_1")
        // 預設使用 .front,最靠近使用者
    
    ResizableRobotView(model: "Robot_2")
        .alignmentGuide(.depthPodium) { d in d[.center] } // 對齊中心,位置居中
    
    ResizableRobotView(model: "Robot_3")
        .alignmentGuide(.depthPodium) { d in d[.back] } // 對齊背面,位置最遠
}

這種做法透過語義化的方式定義了物件的「重要性深度」,而非硬編碼偏移量。

rotation3DLayout:具備佈局感知的旋轉

這是本次更新中最值得架構師關注的功能。在 visionOS 中,我們必須區分「視覺效果」與「幾何佈局」。

視覺效果 vs. 幾何框架

  • rotation3DEffect僅旋轉像素,不改變佈局框架。視覺上(紅色線框)模型已旋轉,但佈局系統認知的框架(藍色虛線框)依然保持原樣,這會導致旋轉後的物件與鄰近元素發生碰撞或重疊
  • rotation3DLayout這是「佈局感知」的旋轉

當應用 rotation3DLayout 時,系統會計算旋轉後的 軸向對齊邊界框(Axis-aligned Bounding Box)。這意味著藍色佈局框會重新計算以緊密貼合旋轉後的紅色視覺框。在 HStack 中,這會觸發重新佈局,自動推開鄰近物件,為旋轉後的幾何體騰出空間。這對於需要動態調整的空間 UI(如火箭噴發動畫或 3D 輪播圖)至關重要。

空間容器與疊加:SpatialContainer 與 spatialOverlay

為了組織更複雜的 3D 視圖結構,visionOS 2 提供了兩項核心工具:

俄羅斯娃娃:SpatialContainer

SpatialContainer 遵循「俄羅斯娃娃 Nesting Dolls」式的設計哲學。它允許嵌套的視圖共享同一個 3D 座標空間。這讓開發者可以一次性對所有子視圖應用 3D 對齊(如 bottomFront),確保複雜的複合物件在空間中作為一個整體存在。

裝飾性疊加:spatialOverlay

當我們需要在 3D 模型下方添加「選中環 Selection Ring」等裝飾時,spatialOverlay 比起傳統的 ZStack 更具戰略意義:

  • 它讓裝飾元件共享主體物件的幾何邊界
  • 開發者可以使用 .bottom 對齊直接將光圈貼合在機器人足部,無需手動計算模型的高度偏移,顯著減少了開發錯誤

實戰應用:構建 debugBorder3D 偵錯工具

為了體現上述 API 的組合價值,我們可以開發一個 3D 線框偵錯工具。其實作邏輯完美體現了「利用 2D 組件構建 3D 結構」的開發哲學。

實作架構解析

  1. 空間同步:使用 spatialOverlay 確保邊框與被測物件在同一個空間維度
  2. 深度合成:利用 ZStack 結合 Spacer 來撐開前後兩面的 2D 邊框
  3. 佈局感知的旋轉:將上述結構再次嵌套並應用 rotation3DLayout 旋轉 90 度,生成左右兩面的邊框
extension View {
    func debugBorder3D() -> some View {
        self.spatialOverlay {
            ZStack {
                // 前後平面
                ZStack {
                    Rectangle().stroke(.blue, lineWidth: 2)
                    Spacer().frame(depth: nil) // 彈性深度,填滿容器
                    Rectangle().stroke(.blue, lineWidth: 2)
                }
                
                // 左右平面(透過旋轉達成)
                ZStack {
                    Rectangle().stroke(.blue, lineWidth: 2)
                    Spacer().frame(depth: nil) // 彈性深度,填滿容器
                    Rectangle().stroke(.blue, lineWidth: 2)
                }
                .rotation3DLayout(.degrees(90), axis: .y)
            }
        }
    }
}

從平面到空間的最後一哩路

SwiftUI 在 3D 空間佈局上的進化,象徵著空間運算已步入成熟期。對於架構師而言,這意味著我們能以更少的模板代碼、更強的狀態管理能力來構建 3D 體驗。

在選擇技術路徑時,請遵循「Better Together」原則:

  • 選擇 SwiftUI:處理 UI 狀態、動態佈局、自動適應(Resizing)以及與數據驅動的動畫
  • 選擇 RealityKit:處理複雜的物理模擬(如碰撞、重力)或高效能的底層渲染

隨著佈局不再受限於螢幕邊框,開發者的挑戰已從「如何對齊像素」轉變為「如何定義空間中的交互深度」。空間運算的時代已經開啟,現在正是你重新定義交互維度的最佳契機。

分享文章

已複製到剪貼板

主題文章

查看 WWDC25

超級感謝

關於 XcodeProject

XcodeProject 創立於 2023,致力於協助開發者探索 Apple 的創新世界,學習在 iOS、iPadOS、macOS、tvOS、visionOS 與 watchOS 上開發 App,發現眾多技術與框架,讓開發者獲得更多能力。


Contacts

Ricky Chuang

XcodeProject

RickyChuang.xcodeproj@gmail.com

XcodeProject 聯絡

contact.xcodeproj@gmail.com

最新文章