You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftData中如何在其他视图访问@Query包装的items变量?

解决SwiftData跨视图访问响应式Item数组的问题

针对你的需求,有两种简单可行的方法,既能保持数组的响应式更新,又能在addFolderSheet中访问Item列表:

方法一:在addFolderSheet中直接使用@Query

你可以在子视图中单独声明@Query来获取Item数组,只要视图能拿到modelContext(通过@Environment注入),这个查询就会自动保持响应式,和父视图的@Query一样会实时更新数据。

修改后的addFolderSheet代码:

struct AddFolderSheet: View { // Swift类型名建议大写开头
    @Environment(\.dismiss) private var dismiss
    @Environment(\.modelContext) var modelContext
    @State private var name: String = ""
    @State private var selectedItems: Set<Item> = [] // 保存选中的Item
    @Query var items: [Item] // 直接声明Query获取所有Item
    
    var body: some View {
        NavigationStack{
            Form {
                Section{
                    TextField("Folder Name", text: $name)
                }
                Section("Select Items to Sort"){
                    ForEach(items) { item in
                        HStack {
                            Text(item.itemName)
                            Spacer()
                            // 添加选中状态标识
                            Image(systemName: selectedItems.contains(item) ? "checkmark.circle.fill" : "circle")
                                .foregroundColor(.blue)
                        }
                        .onTapGesture {
                            if selectedItems.contains(item) {
                                selectedItems.remove(item)
                            } else {
                                selectedItems.insert(item)
                            }
                        }
                    }
                }
            }
            .navigationTitle("New Folder")
            .toolbar {
                ToolbarItemGroup(placement: .topBarLeading) {
                    Button("Cancel") {dismiss()}
                }
                ToolbarItemGroup(placement: .topBarTrailing) {
                    Button("Save") {
                        let folder = Folder(folderName: name)
                        // 将选中Item关联到新文件夹
                        for item in selectedItems {
                            item.folder = folder // 需确保Item模型有folder关联属性
                        }
                        modelContext.insert(folder)
                        dismiss()
                    }
                }
            }
        }
    }
}

注意:需要给Item和Folder模型设置正确的关联关系,比如在Item中添加@Relationship(inverse: \Folder.items) var folder: Folder?,在Folder中添加var items: [Item]? = []。

方法二:从父视图传递items数组

如果不想在子视图中重复写@Query,可以直接把父视图的items数组传递给addFolderSheet,父视图的items是响应式数组,传递后子视图也能实时拿到更新后的内容。

首先修改父视图的sheet调用逻辑(假设用.sheet弹出):

// 在ItemsListView的body中添加弹出按钮
@State private var showAddFolderSheet = false

var body: some View {
    // 原有视图内容...
    
    Button("Add Folder") {
        showAddFolderSheet = true
    }
    .sheet(isPresented: $showAddFolderSheet) {
        AddFolderSheet(items: items) // 传递父视图的items数组
    }
}

然后修改addFolderSheet的代码:

struct AddFolderSheet: View {
    @Environment(\.dismiss) private var dismiss
    @Environment(\.modelContext) var modelContext
    @State private var name: String = ""
    @State private var selectedItems: Set<Item> = []
    let items: [Item] // 接收父视图传递的数组
    
    var body: some View {
        // 其余代码和方法一一致,仅去掉@Query声明
        NavigationStack{
            Form {
                Section{
                    TextField("Folder Name", text: $name)
                }
                Section("Select Items to Sort"){
                    ForEach(items) { item in
                        HStack {
                            Text(item.itemName)
                            Spacer()
                            Image(systemName: selectedItems.contains(item) ? "checkmark.circle.fill" : "circle")
                                .foregroundColor(.blue)
                        }
                        .onTapGesture {
                            if selectedItems.contains(item) {
                                selectedItems.remove(item)
                            } else {
                                selectedItems.insert(item)
                            }
                        }
                    }
                }
            }
            .navigationTitle("New Folder")
            .toolbar {
                ToolbarItemGroup(placement: .topBarLeading) {
                    Button("Cancel") {dismiss()}
                }
                ToolbarItemGroup(placement: .topBarTrailing) {
                    Button("Save") {
                        let folder = Folder(folderName: name)
                        for item in selectedItems {
                            item.folder = folder
                        }
                        modelContext.insert(folder)
                        dismiss()
                    }
                }
            }
        }
    }
}

补充说明

  • 两种方法都能保持响应式:方法一通过@Query直接监听数据变化,方法二依赖父视图传递的响应式数组自动更新。
  • 确保数据模型的关联关系配置正确,否则无法完成Item到Folder的关联存储。

内容的提问来源于stack exchange,提问作者snide_forever

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 02:20:55