核心数据编程指南:将变化与瞬态属性合并

时间:2017-03-02 14:16:12

标签: ios swift core-data

我目前正在通过Apple的Core Data Programming Guide阅读并遇到将瞬态属性合并更改Managed Objects and References的最后一段)。它与awakeFromFetch()refresh(_:mergeChanges:)一起处理Core Data的瞬态属性。

不幸的是,我无法重现所描述的行为。考虑到某些领域的指南似乎不足,我想知道该段的内容是否正确。

我使用Single View Application模板并选中Use Core Data来验证断言:

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
}

人员+ 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")
}

输出

#  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".

将生成的输出与指南中的摘录进行比较后的结果:

  1. 如上所述,更改不会导致缓存的瞬态派生属性自动更新。
  2. 最初将瞬态值恢复为 Sarit Smith ,而不是 Sarit Jones
  3. 与指南提出的声明相反,在应用预刷新值后第二次调用awakeFromFetch(),正确更新瞬态值。
  4. 我忽略了什么吗?我的代码是问题吗?该段落不足吗?

    非常感谢提前。

0 个答案:

没有答案