如何使用 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 应用程序提供了强大而灵活的工具,我们可以期待在这个全新的平台上开发出令人惊叹的应用体验。

相关推荐
明月看潮生40 分钟前
青少年编程与数学 01-011 系统软件简介 07 iOS操作系统
ios·青少年编程·操作系统·系统软件
90后的晨仔2 小时前
RxSwift 框架解析
前端·ios
大熊猫侯佩7 小时前
由一个 SwiftData “诡异”运行时崩溃而引发的钩深索隐(五)
swiftui·swift·apple watch
大熊猫侯佩7 小时前
由一个 SwiftData “诡异”运行时崩溃而引发的钩深索隐(四)
数据库·swiftui·apple watch
可爱小仙子7 小时前
ios苹果系统,js 滑动屏幕、锚定无效
前端·javascript·ios
未来猫咪花7 小时前
# Flutter状态管理对比:view_model vs Riverpod
flutter·ios·android studio
咕噜企业签名分发-淼淼11 小时前
开发源码搭建一码双端应用分发平台教程:逐步分析注意事项
android·ios
键盘敲没电21 小时前
【IOS】GCD学习
学习·ios·objective-c·xcode
SY.ZHOU21 小时前
Significant Location Change
macos·ios·cocoa
MaoJiu1 天前
Flutter造轮子系列:flutter_permission_kit
flutter·swiftui