为啥保存托管对象上下文更改 isDeleted 值?
Posted
技术标签:
【中文标题】为啥保存托管对象上下文更改 isDeleted 值?【英文标题】:Why saving managed object context changes isDeleted value?为什么保存托管对象上下文更改 isDeleted 值? 【发布时间】:2020-06-27 01:42:32 【问题描述】:我正在使用 SwiftUI 和 Core Data 编写一个 ios 应用程序。我对 Core Data 很陌生,并试图理解一些东西:
为什么尝试 self.moc.save() 将 self.item.isDeleted 从 true 更改为 false ? 它发生在我删除核心数据对象(isDeleted 更改为 true)之后,但稍后保存托管对象上下文将其更改为 false。这是为什么呢?
这是一个例子:
ContentView.swift
import SwiftUI
struct ContentView: View
@Environment(\.managedObjectContext) var moc
var fetchRequest: FetchRequest<Item>
var items: FetchedResults<Item> fetchRequest.wrappedValue
var body: some View
NavigationView
List
ForEach(items, id: \.self) item in
NavigationLink(destination: DetailsView(item: item))
Text("\(item.name ?? "default item name")")
.navigationBarTitle("Items")
.navigationBarItems(
leading:
Button(action:
for number in 1...3
let item = Item(context: self.moc)
item.date = Date()
item.name = "Item \(number)"
do
try self.moc.save()
catch
print(error)
)
Text("Add 3 items")
)
init()
fetchRequest = FetchRequest<Item>(entity: Item.entity(), sortDescriptors: [
NSSortDescriptor(keyPath: \Item.name, ascending: true)
])
DetailsView.swift
import SwiftUI
struct DetailsView: View
@Environment(\.managedObjectContext) var moc
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var item: Item
var body: some View
VStack
Text("\(item.name ?? "default item name")")
.navigationBarItems(
trailing:
Button(action:
self.moc.delete(self.item)
print(self.item.isDeleted)
self.presentationMode.wrappedValue.dismiss()
print(self.item.isDeleted)
do
try self.moc.save()
print(self.item.isDeleted)
catch
print(error)
)
Text("Delete")
.foregroundColor(.red)
)
.onDisappear
print(self.item.isDeleted)
if !self.item.isDeleted
print(self.item.isDeleted)
self.item.name = "new name"
print(self.item.isDeleted)
do
try self.moc.save()
catch
print(error)
我预期会发生的事情:
-
self.moc.delete(self.item) 将删除一个对象并将 self.item.isDeleted 标记为 true。
尝试 self.moc.save 将保存 moc
if !self.item.isDeleted 如果项目被删除,将阻止代码执行(没有这个,我得到一个错误:Mutating a managed object (...) after it has been removed)
没有用。我在几行上添加了 print(self.item.isDeleted) 并在这些行上添加断点以检查到底发生了什么。
发生的事情是这样的:
-
self.moc.delete(self.item) 删除了一个对象并将 self.item.isDeleted 标记为 true。
尝试 self.moc.save 保存的 moc 和...
self.item.isDeleted 改为 false
如果 !self.item.isDeleted 没有阻止代码执行,因为此时 isDeleted 为 false。
这是一个错误吗?或者我不理解 Core Data 对象的生命周期和 isDeleted 的变化?
【问题讨论】:
删除 CoreData 实体后,无论如何都不应该更改它。你可以做的是,你为每个被删除的实体存储一个自己的值。当您想删除一个项目时,您只需将该布尔值更改为 true。然后你可以在你的 View/FetchRequest 的任何地方使用它。您必须小心,因为该实体没有被删除。您可以在一段时间后使用 isDeleted 删除对象。 谢谢,我已经用类似的方法解决了。我将@State private var itemExists = true
添加到DetailsView 中,删除后我正在更改它的值。
【参考方案1】:
为什么要尝试 self.moc.save() 将 self.item.isDeleted 从 true 更改为 错误的?它发生在我删除核心数据对象(isDeleted 更改 为 true),但稍后保存托管对象上下文会将其更改为 false。 这是为什么呢?
它的行为与记录相同 - 返回 true before 保存,而不是在其他情况下
这是NSManagedObject
的 Apple 文档快照:
总结
一个布尔值,指示托管对象是否 在下次保存期间删除。声明
var isDeleted: Bool get Discussion
如果 Core Data 将要求持久存储删除对象,则为 true 在下一次保存操作期间,否则为假。它可能返回 false 在其他时候,尤其是在对象被删除之后。这 它将停止返回 true 的即时性取决于 对象正在被删除。如果接收器有故障, 访问此属性不会导致它触发。
【讨论】:
以上是关于为啥保存托管对象上下文更改 isDeleted 值?的主要内容,如果未能解决你的问题,请参考以下文章