如何为同一SwiftData模型创建两个独立存储?
在SwiftData中为同一模型创建独立存储的方案
核心思路
SwiftData支持为同一模型类创建多个独立的ModelContainer,每个容器对应单独的存储文件,以此实现数据的隔离。你可以通过配置不同的ModelConfiguration(指定名称或存储路径)来区分不同的存储容器。
步骤1:更新模型(可选但推荐)
为了实现“最近查看10条”的需求,需要给模型添加时间属性用于排序:
@Model class BasicTrainInfo { @Attribute(.unique) let number: String @Attribute(.unique) let technicalNumber: String @Attribute var createdAt: Date = Date() // 新增:记录数据添加时间 init(number: String, technicalNumber: String) { self.number = number self.technicalNumber = technicalNumber } }
步骤2:创建两个独立的ModelContainer
通过指定ModelConfiguration的name参数,让SwiftData自动生成独立的存储文件:
// 收藏列车的容器 let favoriteTrainContainer: ModelContainer = { let schema = Schema([BasicTrainInfo.self]) let config = ModelConfiguration(name: "FavoriteTrains", schema: schema) do { return try ModelContainer(for: schema, configurations: config) } catch { fatalError("初始化收藏容器失败:\(error)") } }() // 最近查看列车的容器 let recentTrainContainer: ModelContainer = { let schema = Schema([BasicTrainInfo.self]) let config = ModelConfiguration(name: "RecentTrains", schema: schema) do { return try ModelContainer(for: schema, configurations: config) } catch { fatalError("初始化最近查看容器失败:\(error)") } }()
步骤3:在视图中使用对应容器的数据
方式1:环境注入ModelContext
在父视图中为不同子视图注入对应容器的ModelContext,子视图的@Query会自动使用该上下文查询数据:
struct MainView: View { var body: some View { TabView { FavoriteTrainsListView() .environment(\.modelContext, favoriteTrainContainer.mainContext) .tabItem { Label("收藏", systemImage: "star.fill") } RecentTrainsListView() .environment(\.modelContext, recentTrainContainer.mainContext) .tabItem { Label("最近查看", systemImage: "clock.fill") } } } } // 收藏列车列表 struct FavoriteTrainsListView: View { @Query private var favoriteTrains: [BasicTrainInfo] var body: some View { List(favoriteTrains) { train in Text(train.number) } } } // 最近查看列车列表(限制显示10条,按时间倒序) struct RecentTrainsListView: View { @Query(sort: \.createdAt, order: .reverse, limit: 10) private var recentTrains: [BasicTrainInfo] var body: some View { List(recentTrains) { train in Text(train.number) } } }
方式2:直接在@Query中指定容器
如果不想依赖环境注入,可以在初始化@Query时直接指定对应的容器:
struct FavoriteTrainsListView: View { @Query private var favoriteTrains: [BasicTrainInfo] init() { _favoriteTrains = Query(model: BasicTrainInfo.self, container: favoriteTrainContainer) } var body: some View { List(favoriteTrains) { train in Text(train.number) } } }
步骤4:操作对应存储的数据
添加或删除数据时,使用对应容器的ModelContext:
// 添加到收藏 func addToFavorites(train: BasicTrainInfo) { let context = favoriteTrainContainer.mainContext context.insert(train) try? context.save() } // 添加到最近查看(避免重复) func addToRecent(train: BasicTrainInfo) { let context = recentTrainContainer.mainContext let existing = try? context.fetch(FetchDescriptor<BasicTrainInfo>(predicate: #Predicate { $0.number == train.number })).first if existing == nil { context.insert(train) try? context.save() } }
内容的提问来源于stack exchange,提问作者José María
相关产品推荐
相关产品推荐

