我是SwiftUI的新手,对于我的第一个应用程序,我决定try SwiftData,因为我不想以后再把它转换成SwiftData.我的应用程序有计时器(MyTimer),每个计时器都有一个名称和几个重置,每个重置都有一个日期和一个文本字符串.我希望用户能够 Select 一个MyTimer,并查看其重置列表,然后从那里能够编辑或删除它们中的任何一个.因此,我的第一个视图允许创建MyTimer并向其添加重置.第二个视图显示所选MyTimer的重置列表.
我的问题是,当我删除多个重置时,重置数组似乎没有更新,如果从列表的同一行删除第二个重置,它会try 删除已经删除的重置,然后我得到错误:线程1:致命错误:此方法没有准备好操作脱离其托管对象上下文的备份数据.关系将需要由OBJECTID深度复制,才能发挥作用.
以下是APP数据模型文件的代码:
import Foundation
import SwiftData
import SwiftUI
@Model
final class MyTimer {
var id: String
var name: String
@Relationship(deleteRule: .cascade)
var resets: [Reset]
@Transient
var sortedResets: [Reset] {
print(resets.count)
return self.resets.sorted { $0.date > $1.date }
}
init(_ name: String = "",
startDate: Date = .now) {
let id = UUID().uuidString
self.id = id
self.name = name
self.resets = [Reset(text: "Started On", date: startDate)]
}
}
@Model
class Reset: Identifiable {
var id: String
var text: String
var date: Date
init(text: String, date: Date) {
self.id = UUID().uuidString
self.text = text
self.date = date
}
}
应用程序文件:
import SwiftUI
import SwiftData
@main
struct SwiftDataHabitTestApp: App {
let container = try? ModelContainer(for: MyTimer.self, Reset.self)
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(container!)
}
}
内容视图:
import SwiftUI
import SwiftData
struct 内容视图: View {
@Environment(\.modelContext) private var modelContext
@State var timerName: String = ""
@State var resetViewShowing = false
@State var timerForResetView: MyTimer?
@Query(sort: \MyTimer.name) var allTimers: [MyTimer]
var body: some View {
ZStack {
VStack {
TextField(text: $timerName, prompt: Text("Name your Timer")) {
Text("Name:")
}
Button {
let newTimer = MyTimer(timerName)
modelContext.insert(newTimer)
} label: {
Text("Create Timer")
}
List {
ForEach(allTimers){ dispTimer in
Text(dispTimer.name)
Button {
let newReset = Reset(text: "New REset", date: .now)
dispTimer.resets.append(newReset)
try? modelContext.save()
} label: {
Text("Reset")
}
Button {
resetViewShowing = true
timerForResetView = dispTimer
} label: {
Text("View Resets")
}
}
.onDelete(perform: { indexSet in
indexSet.forEach { index in
modelContext.delete(allTimers[index])
}
})
}
}
.padding()
if resetViewShowing {
ResetListView(dispTimer: timerForResetView!)
}
}
}
}
重置列表视图
import SwiftUI
import SwiftData
struct ResetListView: View {
@Environment(\.modelContext) private var modelContext
@State var dispTimer: MyTimer
var body: some View {
// var resetList: [Reset] = dispTimer.resets.sorted { $0.date > $1.date }
List {
ForEach(dispTimer.resets) {
Text($0.text)
}
.onDelete(perform: { indexSet in
indexSet.forEach { index in
print("index: \(index)")
print("length of resets: \(dispTimer.resets.count)")
modelContext.delete(dispTimer.resets[index])
do {
try modelContext.save() <<---- Error: Thread 1: Fatal error: This method isn't prepared to operate on a backing data that's unmoored from its managed object context. Relationships will need to be deep copied by objectID for that to work.
} catch {
print("error saving")
}
}
})
}
}
}
我try 了几种方法来使用重置的排序数组,我希望它按日期顺序显示在列表中,在视图中将它们排序到一个变量中,或者使用MyTimer中的计算(computed)属性,但我得到了一个不同的错误:Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1a8a4fad8)
,它出现在Reset的Date属性的getter中,我也try 过使用.onDelete而不是使用.swpeActions,但这似乎没有解决问题.