I am writing an iOS app using SwiftUI and Core Data. I am very new to Core Data and try to understand something:
Why try self.moc.save() changes self.item.isDeleted from true to false? It happens after I delete a Core Data object (isDeleted changes to true), but later saving managed object context changes it to false. Why is that?
Here is an example:
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)
}
}
}
}
}
What I expected will happen:
It didn't work. I have added print(self.item.isDeleted) on few lines and breakpoints on those lines to check what exactly happens.
What happened is this:
Is it a bug? Or I don't understand the life cycle of Core Data objects and isDeleted changes as it should?
Why try self.moc.save() changes self.item.isDeleted from true to false? It happens after I delete a Core Data object (isDeleted changes to true), but later saving managed object context changes it to false. Why is that?
It behaves as documented - returns true before save, and not in other cases
Here is snapshot of Apple documentation for NSManagedObject
:
Summary
A Boolean value that indicates whether the managed object will be deleted during the next save. Declaration
var isDeleted: Bool { get } Discussion
true if Core Data will ask the persistent store to delete the object during the next save operation, otherwise false. It may return false at other times, particularly after the object has been deleted. The immediacy with which it will stop returning true depends on where the object is in the process of being deleted. If the receiver is a fault, accessing this property does not cause it to fire.