I am currently reading the Master Data Programming Guide through Apple and have encountered combining changes with transient properties (last paragraph Managed Objects and Links ). It is associated with the basic properties of the transition data in combination with awakeFromFetch()and refresh(_:mergeChanges:).
Unfortunately, I cannot reproduce the described behavior. Given that the guidance is apparently inadequate in some areas, I wonder if the content of this paragraph is correct.
I use the Single View Applicationc template Use Core Datato validate claims:
AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
func check(_ person: Person) {
print(" check: \(person.firstName ?? "nil") | \(person.lastName ?? "nil") | \(person.fullName ?? "nil")\n")
}
let viewContext = persistentContainer.viewContext
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = Person.fetchRequest()
let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
try! persistentContainer.persistentStoreCoordinator.execute(batchDeleteRequest, with: viewContext)
print("# persistent store: insert\n")
weak var person = Person(context: viewContext)
person!.firstName = "Sarit"
person!.lastName = "Smith"
check(person!)
try! viewContext.save()
let context1 = persistentContainer.newBackgroundContext()
let context2 = persistentContainer.newBackgroundContext()
context2.performAndWait {
print("# context2: fetch\n")
let fetchRequest: NSFetchRequest<Person> = Person.fetchRequest()
let person = try! context2.fetch(fetchRequest).first!
check(person)
context1.performAndWait {
print("# context1: fetch\n")
let fetchRequest: NSFetchRequest<Person> = Person.fetchRequest()
let person = try! context1.fetch(fetchRequest).first!
check(person)
print("# context1: modify\n")
person.firstName = "Fiona"
check(person)
try! context1.save()
}
print("# persistent store: check\n")
viewContext.performAndWait {
let fetchRequest: NSFetchRequest<Person> = Person.fetchRequest()
let person = try! viewContext.fetch(fetchRequest).first!
check(person)
}
print("# context2: modify\n")
person.lastName = "Jones"
check(person)
print("# context2: refresh\n")
context2.refresh(person, mergeChanges: true)
check(person)
}
return true
}
Person + CoreDataClass.swift
override public func awakeFromFetch() {
super.awakeFromFetch()
print("-> awakeFromFetch\n")
print(" before: \(firstName ?? "nil") | \(lastName ?? "nil") | \(fullName ?? "nil")")
fullName = "\(firstName!) \(lastName!)"
print(" after: \(firstName ?? "nil") | \(lastName ?? "nil") | \(fullName ?? "nil")\n")
}
Output
check: Sarit | Smith | nil
-> awakeFromFetch
before: Sarit | Smith | nil
after: Sarit | Smith | Sarit Smith
check: Sarit | Smith | Sarit Smith
-> awakeFromFetch
before: Sarit | Smith | nil
after: Sarit | Smith | Sarit Smith
check: Sarit | Smith | Sarit Smith
check: Fiona | Smith | Sarit Smith (1.)
// (1.) [...] which causes the cached fullName to be updated to "Fiona Smith"[...]
-> awakeFromFetch
before: Fiona | Smith | nil
after: Fiona | Smith | Fiona Smith
check: Fiona | Smith | Fiona Smith
check: Sarit | Jones | Sarit Smith (1.)
// (1.) [...] which causes the cached fullName to be updated to "Sarit Jones".
-> awakeFromFetch
before: Fiona | Smith | nil
after: Fiona | Smith | Fiona Smith
-> awakeFromFetch
before: Fiona | Jones | Sarit Smith (2.)
after: Fiona | Jones | Fiona Jones (3.)
check: Fiona | Jones | Fiona Jones (3.)
// The transient value, fullName, was also changed prior to the refresh.
// (2.) After the refresh, its value is restored to "Sarit Jones".
// (3.) However, to be correct, it should be "Fiona Jones".
:
- , , .
- , .
- , ,
awakeFromFetch() , prerefresh, .
- ? ? ?
.