VisionPro开发实践2 - 构建数据模型

1. 定义数据对象

创建一个Model文件夹,并在其中添加Bag文件,内容如下:

rust 复制代码
struct Bag: Identifiable, Codable, Hashable {
    let id: Int
    let name: String
    let title: String
    let desc: String
}

2. 通过JSON文件加载数据

2.1. 定义ViewModel

在Model文件夹下新建一个ViewModel文件,内容如下:

typescript 复制代码
import Foundation

class BagViewModel: ObservableObject {
    @Published var bags: [Bag] = []
    
    init() {
        load()
    }
    
    func load() {
        if let url = Bundle.main.url(forResource: "bags", withExtension: "json"),
           let data = try? Data(contentsOf: url),
           let bags = try? JSONDecoder().decode([Bag].self, from: data) {
            self.bags = bags
        }
    }
}

这里声明了一个 ObserverableObject,用来加载JSON文件中的内容,并用于UI界面的展示,后面会讲到应用场景。

这个BagViewModel对象中定一个了一个bags的Bag数组对象,用来保存从文件中读取的数据。

2.2. 创建JSON文件

在根目录下创建一个bag.json的文件,并根据之前的Bag模型来定义数据,数据案例如下:

css 复制代码
[  {    "id": 1,    "name": "Speedy",    "title": "LV x YK SPEEDY BANDOULIÈRE 20 手袋",    "desc": "路易威登 x 草间弥生合作系列推出 LV x YK Speedy Bandoulière 20 手袋,迸发无限波点主题的创意能量。鲜明波点经由丝印工艺呈现于 Monogram Empreinte 牛皮革之上,呼应这位知名日本艺术家作品中的一贯主题,礼赞艺术思维与精湛匠艺的结合。南瓜形状装饰再添草间弥生的视觉名片。"  },  {    "id": 2,    "name": "Neonoe",    "title": "NÉONOÉ 中号手袋 大象灰/奶白色 压纹粒面牛皮",    "desc": "本款 NéoNoé 中号水桶包将 LV 字母和 Monogram 花卉先印染后压印于皮革,以瞩目观感迷惑视觉。内袋可妥善安置贵重物品,可调节肩带实现肩背或斜挎。"  }]

本文件的加载与上文提到的

less 复制代码
Bundle.main.url(forResource: "bags", withExtension: "json")

语句相对应。

2.3. 数据应用

先看一下界面效果,通过加载JSON文件,把bags数组呈现在右侧边栏中

less 复制代码
struct ContentView: View {
    
    @EnvironmentObject var store: ViewStore
    @EnvironmentObject var viewModel: BagViewModel

    var body: some View {
        
        NavigationSplitView {
            List(viewModel.bags, id: .self.id, selection: $store.selection) { bag in
                HStack(alignment: .center) {
                    Model3D(named: bag.name, bundle: realityKitContentBundle)
                        .frame(width: 20, height: 20)
                        .frame(depth: 10, alignment: .center)
                        .rotation3DEffect(Angle(degrees: bag.name == "DAUPHINE" ? 179: 0), axis: .y)
                        .scaleEffect(x: 0.1, y: 0.1, z: 0.1)
                        .padding(.init(top: 0, leading: 10, bottom: 0, trailing: 10))
                        
                    Text("(bag.title)")
                }
            }
        } detail: {
            ItemDetailView()
        }
        .environmentObject(store)
        .environmentObject(viewModel)
        
    }
}

3. 数据传递

因为我要在多个View之间传递数据,目前没想到更好的办法,就先用EnviromentObject来进行环境变量传递。

可以看到在上文中,ContentView就是用这种方式加载了环境变量viewModel和store,那么这两个环境变量是在哪里初始化的呢? 我们看一下APP的初始View:

scss 复制代码
import SwiftUI

@main
struct VisionBagApp: App {
    @StateObject var store = ViewStore()
    @ObservedObject var viewModel = BagViewModel()
    
    var body: some Scene {
        
        WindowGroup {
            ContentView()
                .environmentObject(store)
                .environmentObject(viewModel)
        }

        ImmersiveSpace(id: "ImmersiveSpace") {
            ImmersiveView()
                .environmentObject(store)
                .environmentObject(viewModel)
        }
        
    }
    
    init() {
        // Register all the custom components and systems that the app uses.
        RotationComponent.registerComponent()
        RotationSystem.registerSystem()
        TraceComponent.registerComponent()
        TraceSystem.registerSystem()
    }
}

在这里完成了store和viewModel的初始化,尤其是viewModel会在这里完成JSON文件的读取。并传递到下一级的View当中。

这里我们就完成了数据模型的创建和展示,后面的文章会具体讲一下VisionOS的ImmersiveSpace和一些操作3D手势。

相关推荐
子兮曰1 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰1 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万1 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝1 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师1 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学1 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端