如何使用 SwiftUI 构建 visionOS 应用

前言

Apple Vision Pro 即将推出,现在是看看 SwiftUI API 的完美时机,这使我们能够将我们的应用程序适应 visionOS 提供的沉浸式世界。苹果表示,构建应用程序的最佳方式是使用 Swift 和 SwiftUI。下面,我们将学习如何使用 SwiftUI 构建 visionOS 应用程序。

Windows

我喜欢 SwiftUI 的一点是它如何自动适应平台。你无需执行任何操作即可在 visionOS 上运行使用 SwiftUI 编写的应用程序。它可以即插即用。但是,你始终可以通过向前移动并适应平台功能来改进用户体验。

swift 复制代码
struct ContentView: View {
    var body: some View {
        NavigationSplitView {
            List {
            // 列表内容
            }
            .navigationTitle("Models")
            .toolbar {
                ToolbarItem(placement: .bottomOrnament) {
                    Button("open", systemImage: "doc.badge.plus") {
                        
                    }
                }
                
                ToolbarItem(placement: .bottomOrnament) {
                    Button("open", systemImage: "link.badge.plus") {
                        
                    }
                }
            }
        } detail: {
            Text("Choose something from the sidebar")
        }
    }
}

在上面的示例中,我们使用了称为 bottomOrnament 的新工具栏放置。 visionOS 中的装饰是位于窗口外部的位置,用于呈现与窗口连接的控件。你还可以通过使用新的 ornament 视图修改器手动创建它们。

swift 复制代码
struct ContentView: View {
    var body: some View {
        NavigationSplitView {
            List {
            // 列表内容
            }
            .navigationTitle("Models")
            .ornament(attachmentAnchor: .scene(.leading)) {
                // 在此处放置你的视图
            }
        } detail: {
            Text("Choose something from the sidebar")
        }
    }
}

新的 ornament 视图修改器允许我们为其连接的窗口创建一个具有特定锚点的装饰。将你的应用内容适应 visionOS 提供的沉浸式体验的另一种方法是使用 transform3DEffectrotation3DEffect 视图修改器来加入深度效果。如下图:

Volumes

你的应用程序可以在 visionOS 上的同一场景中并排显示 2D 和 3D 内容。在这种情况下,我们可以使用 RealityKit 框架来呈现 3D 内容。例如,RealityKit 为我们提供了 Model3D SwiftUI 视图,允许我们从 USDZ 或实际文件中显示 3D 模型。

swift 复制代码
struct ContentView: View {
    var body: some View {
        NavigationSplitView {
            List(Model.all) { model in
                NavigationLink {
                    Model3D(named: model.name)
                } label: {
                    Text(verbatim: model.name)
                }
            }
            .navigationTitle("Models")
        } detail: {
            Model3D(named: "robot")
        }
    }
}

Model3D 视图的工作方式类似于 AsyncImage 视图,并异步加载模型。你还可以使用 Model3D 初始化器的另一种变体,它允许你自定义模型配置并添加占位视图。

swift 复制代码
struct ContentView: View {
    var body: some View {
        NavigationSplitView {
            List(Model.all) { model in
                NavigationLink {
                    Model3D(
                        url: Bundle.main.url(
                            forResource: model.name,
                            withExtension: "usdz"
                        )!
                    ) { resolved in
                        resolved
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                    } placeholder: {
                        ProgressView()
                    }
                } label: {
                    Text(verbatim: model.name)
                }
            }
            .navigationTitle("Models")
        } detail: {
            Model3D(named: "robot")
        }
    }
}

在你的应用程序中呈现 3D 内容时,你可以使用 windowStyle 修饰符来启用内容的体积显示。体积样式允许你的内容在第三维中增长,以匹配模型的大小。

对于更复杂的 3D 场景,我们可以使用 RealityView 并填充它以 3D 内容。

swift 复制代码
struct ContentView: View {
    var body: some View {
        NavigationSplitView {
            List(Model.all) { model in
                NavigationLink {
                    RealityView { content in
                        // load the content and add to the scene
                    }
                } label: {
                    Text(verbatim: model.name)
                }
            }
            .navigationTitle("Models")
        } detail: {
            Text("Choose something from the sidebar")
        }
    }
}

沉浸式空间

visionOS 的第三个选项是完全沉浸式体验,允许我们通过隐藏周围的所有内容来专注于你的场景。

swift 复制代码
@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        
        ImmersiveSpace(id: "solar-system") {
            SolarSystemView()
        }
    }
}

正如你在上面的示例中所看到的,我们通过使用 ImmersiveSpace 类型来定义场景。它允许我们通过使用 openImmersiveSpace 环境值来启用它。

swift 复制代码
struct MyMenuView: View {
    @Environment(\.openImmersiveSpace) private var openImmersiveSpace
    
    var body: some View {
        Button("Enjoy immersive space") {
            Task {
                await openImmersiveSpace(id: "solar-system")
            }
        }
    }
}

我们还可以使用 dismissImmersiveSpace 环境值来关闭沉浸式空间。请记住,你一次只能显示一个沉浸式空间。

swift 复制代码
struct SolarSystemView: View {
    @Environment(\.dismissImmersiveSpace) private var dismiss
    
    var body: some View {
        // Immersive experience
        
        Button("Dismiss") {
            Task {
                await dismiss()
            }
        }
    }
}

结论

在介绍了 SwiftUI 在 visionOS 上的应用之后,我们了解到 SwiftUI 可以帮助我们轻松构建适应 visionOS 的应用程序。不仅如此,SwiftUI 还提供了许多方便的工具和修饰符,例如 windowStyle 修饰符,可用于在应用程序中呈现 3D 内容,并使内容根据模型的大小自动适应。通过引入沉浸式空间,我们可以将用户带入全新的体验,让他们沉浸在应用程序的世界中。总的来说,SwiftUI 为构建 visionOS 应用程序提供了强大而灵活的工具,我们可以期待在这个全新的平台上开发出令人惊叹的应用体验。

相关推荐
sakiko_9 小时前
Swift学习笔记42-SwiftUI的属性包装器(讲解+面试)
笔记·学习·ios·swiftui·swift
Patrick_Wilson17 小时前
iOS Safari 按钮点击无响应问题修复指南
前端·ios·safari
随遇丿而安18 小时前
第 3 周:UIButton 点了没反应,因为它默认就没有按压态
ios
思盛iOS签名上架1 天前
App苹果签名有什么作用?
macos·ios·cocoa
CocoaKier2 天前
Facebook广告后台收不到Adjust回传数据,我们排查了一个月终于找到了根因
ios·facebook
weixin_531670893 天前
Interlude起来:动作动画和文字通知哪个更适合休息提醒?Mac上有没有用桌宠做动作引导的软件?
人工智能·macos·mac·swift
FairGuard手游加固3 天前
iOS 游戏加固技术解析:代码混淆、资源加密、内存保护与重签名检测
安全·游戏·macos·unity·ios·objective-c
思盛iOS签名上架3 天前
iOS企业签名原理是什么?
macos·ios·cocoa
Daniel_Coder3 天前
我用 SwiftUI + GRDB 做了一个「按时吃药·服药提醒」App
ios·swiftui·swift·widgetkit