SwiftUI传递SwiftData @Model对象参数时预览编译报错求助
SwiftData @Model对象传递及预览报错解决
问题场景
使用Xcode 15 beta 2开发SwiftData+SwiftUI多视图项目,将@Model标记的Item对象作为参数传入DetailView时,DetailView的预览代码抛出编译错误:
"Type 'Item' does not conform to protocol 'PersistentModel'"
相关代码
ContentView
import SwiftUI import SwiftData struct ContentView: View { @Environment(\.modelContext) private var modelContext @Query private var items: [Item] @State private var selection: Item? var body: some View { NavigationSplitView { List(selection: $selection) { ForEach(items) { item in Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard)) } .onDelete(perform: deleteItems) } .toolbar { ToolbarItem(placement: .navigationBarTrailing) { EditButton() } ToolbarItem { Button(action: addItem) { Label("Add Item", systemImage: "plus") } } } } detail: { DetailView(selection: selection) } .navigationSplitViewStyle(.balanced) } private func addItem() { withAnimation { let newItem = Item(timestamp: Date()) modelContext.insert(newItem) } } private func deleteItems(offsets: IndexSet) { withAnimation { for index in offsets { modelContext.delete(items[index]) } } } } #Preview { ContentView() .modelContainer(for: Item.self, inMemory: true) }
DetailView
import SwiftUI import SwiftData struct DetailView: View { var selection: Item? var body: some View { if let item = selection { Text("Item at \(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))") } else { Text("nothing selected") } } } #Preview { return DetailView(selection: Item(timestamp: Date())) .modelContainer(for: Item.self, inMemory: true) }
Item
import Foundation import SwiftData @Model final class Item { var timestamp: Date init(timestamp: Date) { self.timestamp = timestamp } }
解决方案
1. 修正预览代码:让@Model实例关联ModelContext
直接初始化的Item实例未绑定到任何ModelContext,无法被识别为PersistentModel。需要先创建ModelContainer,将实例插入上下文后再传入DetailView:
修改后的DetailView预览代码:
#Preview { do { // 创建内存容器 let container = try ModelContainer( for: Item.self, configurations: ModelConfiguration(inMemory: true) ) // 创建Item实例并插入上下文 let previewItem = Item(timestamp: Date()) container.mainContext.insert(previewItem) // 传入关联了上下文的实例 return DetailView(selection: previewItem) .modelContainer(container) } catch { return Text("预览初始化失败:\(error.localizedDescription)") } }
2. 确认@Model对象的传递方式
你在ContentView中通过@Query获取Item实例,再将selection传给DetailView的方式是完全正确的。这类从有效ModelContext中获取的实例,本身已经符合PersistentModel协议,可以直接作为参数传递。
原因说明
@Model修饰的类会自动实现PersistentModel协议,但该协议的有效性依赖于实例是否被关联到某个ModelContext。直接调用初始化方法创建的实例处于"游离"状态,未绑定上下文,因此在预览中会触发协议不兼容的报错。必须通过modelContext.insert(_:)将其纳入容器管理后,才能正常使用。
内容的提问来源于stack exchange,提问作者Syd Polk
相关产品推荐
相关产品推荐

