Я пытаюсь обновить и сохранить управляемый объект в одном контексте, а затем получить доступ к обновленному значению атрибута в другом контексте.Документация для 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()
, но это:
- Потенциально влияет на многихбольше объектов, которые не нужно обновлять прямо сейчас.
- Не обеспечивает контроль над изменениями при слиянии.
- Отправляет уведомление об изменениях.
shouldRefreshRefetchedObjects
кажется именно то, что я хочу;кажется, он ничего не делает.Лучший обходной путь, по-видимому, заключается в индивидуальном обновлении объектов, но я предполагаю, что это неэффективно.