我已经编辑了这个问题,试图使其更清晰,并添加了一个 Xcode 项目
要模拟我试图解决的问题,只需按一个按钮,然后在 macOS 中使用来自 SwiftData 的模型打开一个新窗口。
这是 SwiftDataWindowApp 文件,我试图将 ItemModel 传递给 WindowGroup。我希望只是传递整个模型,因为在其他 SwiftData 应用程序中我从来不需要 Id。
import SwiftUI
import SwiftData
@main
struct SwiftDataWindowApp: App {
var body: some Scene {
WindowGroup {
RootView()
.modelContainer(for: [ItemModel.self])
}
// I can't figure out how to pass an ItemModel to WindowGroup this does not work
WindowGroup(for: [ItemModel.self]) { $item in
ItemView(item:$item)
.modelContainer(for:[ItemModel.self])
}
// Example for WindowGroup documentation
// A window group that displays messages.
//WindowGroup(for: Message.ID.self) { $messageID in
//MessageDetail(messageID: messageID)
// }
}
}
在 ItemsButtonView 文件中是我调用 openWindow 的地方
import SwiftUI
struct ItemsButtonView: View {
@Environment(\.openWindow) private var openWindow
let item: ItemModel
var body: some View {
NavigationStack {
VStack(alignment: .leading) {
Text("\(item.name )")
Text("\(item.desc )")
Text("Item at \(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))")
HStack {
Text("Open Item In New Window")
.onTapGesture {
// Open Item in new window
// openWindow(value: item)
print("Open Item Button Presed")
}
}
}
}
}
}
我的模型
import Foundation
import SwiftData
@Model
final class ItemModel {
var timestamp: Date
var name: String
var desc: String
init(timestamp: Date, name: String = "", desc: String = "") {
self.timestamp = timestamp
self.name = name
self.desc = desc
}
}
我想在新窗口中打开的ItemView文件。
import SwiftUI
struct ItemView: View {
let item: ItemModel
var body: some View {
VStack{
Text("Name: \(item.name)")
Text("Description: \(item.desc)")
Text("Date: \(item.timestamp)")
}
.frame(width:600, height:300)
}
}
首先,我认为在这种情况下最好为 ModelContainer 拥有一个属性,而不是为每个 WindowGroup 创建一个新属性
以下示例来自 SwiftData 项目的 Xcode 模板。
var sharedModelContainer: ModelContainer = {
let schema = Schema([ItemModel.self])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
do {
return try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}()
然后你有一个奇怪的 WindowGroup 类型,一个模型类型的数组。由于您只会将一个对象传递给 openWindow,然后传递给视图,因此它不能是数组,而且使用的类型必须符合 Codable,因此模型类型不是一个好主意,最好使用模型的 ID 类型
WindowGroup(for: ItemModel.ID.self)
然后有不同的方法来处理我们得到的ID值,在下面的解决方案中我直接将其解包并加载模型对象,然后将其传递给视图
let context = ModelContext(sharedModelContainer)
if let id, let model = context.model(for: id) as? ItemModel {
ItemView(item: model)
}
场景的完整代码
var body: some Scene {
WindowGroup {
RootView()
}
.modelContainer(sharedModelContainer)
WindowGroup(for: ItemModel.ID.self) { $id in
let context = ModelContext(sharedModelContainer)
if let id, let model = context.model(for: id) as? ItemModel {
ItemView(item: model)
}
}
}