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

如何为SwiftUI的@Query宏指定不同的ModelContainer?

解决方案:通过@Query宏指定自定义ModelContainer

SwiftUI的@Query宏完全支持指定自定义的ModelContainer,不需要手动执行数据获取。你可以通过宏的container参数,传入自定义容器的环境绑定来实现。

步骤1:定义自定义容器的环境键

系统默认的modelContainer环境键专为默认容器设计,你需要为自定义的creationContainer创建专属环境键:

private struct CreationContainerKey: EnvironmentKey {
    static let defaultValue: ModelContainer? = nil
}

extension EnvironmentValues {
    var creationContainer: ModelContainer? {
        get { self[CreationContainerKey.self] }
        set { self[CreationContainerKey.self] = newValue }
    }
}

步骤2:在App层级注入两个容器

将默认容器(捆绑存储)和自定义容器(可编辑存储)都注入到视图环境中:

@main
struct YourApp: App {
    let modelContainer: ModelContainer
    let creationContainer: ModelContainer

    init() {
        // 初始化捆绑存储的默认容器
        let readOnlySchema = Schema([ReadOnlyModel.self])
        guard let bundleDataURL = Bundle.main.url(forResource: "ReadOnlyDatabase", withExtension: "momd") else {
            fatalError("捆绑数据库文件不存在")
        }
        self.modelContainer = try! ModelContainer(for: readOnlySchema, configurations: [
            ModelConfiguration(url: bundleDataURL)
        ])

        // 初始化可编辑的自定义容器
        let editableSchema = Schema([EditableModel.self])
        self.creationContainer = try! ModelContainer(for: editableSchema)
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
                .modelContainer(modelContainer) // 注入默认容器
                .environment(\.creationContainer, creationContainer) // 注入自定义容器
        }
    }
}

步骤3:在视图中用@Query指定目标容器

  • 查询可编辑容器的数据时,通过container参数传入自定义环境键:
struct EditableItemsView: View {
    // 指定查询creationContainer中的数据
    @Query(container: \.creationContainer, sort: \EditableModel.updateTime) 
    private var editableItems: [EditableModel]

    var body: some View {
        List(editableItems) { item in
            Text(item.userContent)
        }
    }
}
  • 查询捆绑存储容器的数据时,直接使用默认的@Query(无需指定container参数):
struct ReadOnlyItemsView: View {
    // 默认使用modelContainer查询
    @Query(sort: \ReadOnlyModel.id) 
    private var readOnlyItems: [ReadOnlyModel]

    var body: some View {
        List(readOnlyItems) { item in
            Text(item.staticContent)
        }
    }
}

关联两个容器数据的场景

如果需要基于可编辑数据的ID匹配捆绑存储中的数据,可以结合两个@Query实现:

struct CombinedDataView: View {
    @Query(container: \.creationContainer) private var editableItems: [EditableModel]
    @Query private var allReadOnlyItems: [ReadOnlyModel]

    var body: some View {
        List(editableItems) { editableItem in
            if let matchedReadOnlyItem = allReadOnlyItems.first(where: { $0.id == editableItem.linkedReadOnlyID }) {
                VStack(alignment: .leading) {
                    Text("用户编辑内容:\(editableItem.userInput)")
                    Text("关联静态数据:\(matchedReadOnlyItem.detail)")
                }
            }
        }
    }
}

如果捆绑存储的数据量极大,全量查询影响性能,你依然可以在视图中通过自定义容器的ModelContext手动查询特定ID的数据,这种场景下手动查询是合理的,但@Query依然能覆盖大部分常规列表展示场景,减少样板代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 00:33:26