Почему NSFetchRequest.shouldRefreshRefetchedObjects не работает? - PullRequest
1 голос
/ 17 июня 2019

Я пытаюсь обновить и сохранить управляемый объект в одном контексте, а затем получить доступ к обновленному значению атрибута в другом контексте.Документация для shouldRefreshRefetchedObjects гласит: :

По умолчанию при извлечении объектов они сохраняют свои текущие значения свойств, даже если значения в постоянном хранилище изменились.Вызов этого метода с параметром YES означает, что при выполнении выборки значения свойств выбранных объектов обновляются с текущими значениями в постоянном хранилище.Это более удобный способ обеспечить согласованность значений свойств управляемого объекта с хранилищем, чем использование refreshObject: mergeChanges: (NSManagedObjetContext) для нескольких объектов по очереди.

Поэтому я подумал, что установивtrue Я бы получил текущие значения после повторной загрузки, без необходимости вручную обновлять отдельные объекты.Однако, похоже, это не так.В macOS 10.14.5 запрос на выборку будет выбирать правильные объекты на основе значений свойств в хранилище, но объекты в памяти по-прежнему имеют устаревшие значения.

Ниже приведен пример кода, иллюстрирующий проблему.Я ожидаю, что он напечатает Old New New, но вместо этого он напечатает Old Old New.

import Foundation
import CoreData

class Entity: NSManagedObject {
    @NSManaged var attribute: String
}

let attribute = NSAttributeDescription()
attribute.name = "attribute"
attribute.attributeType = .stringAttributeType
let entityDescription = NSEntityDescription()
entityDescription.name = "Entity"
entityDescription.properties = [attribute]
entityDescription.managedObjectClassName = Entity.className()
let model = NSManagedObjectModel()
model.entities = [entityDescription]

let coordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
try! coordinator.addPersistentStore(ofType: NSInMemoryStoreType, configurationName: nil, at: nil, options: [:])

let writeContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
writeContext.persistentStoreCoordinator = coordinator
let readContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
readContext.persistentStoreCoordinator = coordinator

let writeEntity = Entity(entity: entityDescription, insertInto: writeContext)
writeContext.performAndWait {
    writeEntity.attribute = "Old"
    try! writeContext.save()
}

var readEntity: Entity? = nil
readContext.performAndWait {
    let request = NSFetchRequest<Entity>(entityName: entityDescription.name!)
    readEntity = try! readContext.fetch(request).first!
    // Initially the attribute should be Old, and that's what's printed
    print(readEntity!.attribute)
}

writeContext.performAndWait {
    writeEntity.attribute = "New"
    try! writeContext.save()
}

readContext.performAndWait {
    let request = NSFetchRequest<Entity>(entityName: entityDescription.name!)
    request.shouldRefreshRefetchedObjects = true
    _ = try! readContext.fetch(request)
    // Now the attribute should be New, but it is still Old
    print(readEntity!.attribute)

    readContext.refresh(readEntity!, mergeChanges: false)
    _ = try! readContext.fetch(request)
    // However, manually refreshing and fetching again does update it to New
    print(readEntity!.attribute)
}

Я знаю refreshAllObjects(), но это:

  1. Потенциально влияет на многихбольше объектов, которые не нужно обновлять прямо сейчас.
  2. Не обеспечивает контроль над изменениями при слиянии.
  3. Отправляет уведомление об изменениях.

shouldRefreshRefetchedObjects кажется именно то, что я хочу;кажется, он ничего не делает.Лучший обходной путь, по-видимому, заключается в индивидуальном обновлении объектов, но я предполагаю, что это неэффективно.

...