Master Data Programming Guide: Merging Changes with Transients

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 {

    // check properties and fire faults
    func check(_ person: Person) {
        print("   check:  \(person.firstName ?? "nil") | \(person.lastName ?? "nil") | \(person.fullName ?? "nil")\n")
    }

    // clear persistent store
    let viewContext = persistentContainer.viewContext
    let fetchRequest: NSFetchRequest<NSFetchRequestResult> = Person.fetchRequest()
    let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
    try! persistentContainer.persistentStoreCoordinator.execute(batchDeleteRequest, with: viewContext)

    // insert person
    print("#  persistent store: insert\n")
    weak var person = Person(context: viewContext)
    person!.firstName = "Sarit"
    person!.lastName = "Smith"
    check(person!)
    try! viewContext.save()

    // create background contexts
    let context1 = persistentContainer.newBackgroundContext()
    let context2 = persistentContainer.newBackgroundContext()

    // run test
    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

#  persistent store: insert    
   check:  Sarit | Smith | nil

#  context2: fetch    
-> awakeFromFetch    
   before: Sarit | Smith | nil
   after:  Sarit | Smith | Sarit Smith    
   check:  Sarit | Smith | Sarit Smith

#  context1: fetch    
-> awakeFromFetch    
   before: Sarit | Smith | nil
   after:  Sarit | Smith | Sarit Smith    
   check:  Sarit | Smith | Sarit Smith

#  context1: modify 
   check:  Fiona  | Smith | Sarit Smith (1.)
   // (1.) [...] which causes the cached fullName to be updated to "Fiona Smith"[...]

#  persistent store: check    
-> awakeFromFetch    
   before: Fiona | Smith | nil
   after:  Fiona | Smith | Fiona Smith    
   check:  Fiona | Smith | Fiona Smith

#  context2: modify    
   check:  Sarit | Jones | Sarit Smith (1.)
   // (1.) [...] which causes the cached fullName to be updated to "Sarit Jones".

#  context2: refresh    
-> 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, .

- ? ? ?

.

+4

Source: https://habr.com/ru/post/1671257/


All Articles