【发布时间】:2019-10-31 05:19:35
【问题描述】:
我正在尝试在一个上下文中更新和保存托管对象,然后在另一个上下文中访问更新后的属性值。 shouldRefreshRefetchedObjectssays的文档:
默认情况下,当您获取对象时,它们会保持当前状态 属性值,即使持久存储中的值具有 改变了。使用参数 YES 调用此方法意味着当 fetch 被执行,获取对象的属性值为 使用持久存储中的当前值进行更新。这是一个更 确保托管对象属性值的便捷方法 与商店一致,而不是使用 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 似乎正是我想要的;它似乎什么也没做。最好的解决方法似乎是单独刷新对象,但我猜这是低效的。
【问题讨论】:
-
在此示例中,要么不保留对
readEntity的引用,要么在获取之前将其标记为“错误”。 -
@paiv 我知道丢弃
readEntity(如上一个示例)将解决它不是最新的问题。但是这个问题是关于使用shouldRefreshRefetchedObjects,它承诺更新与获取请求匹配的现有对象,而无需提前确定哪些对象。 -
如果保持强引用,对象不会被“重取”,标志
shouldRefreshRefetchedObjects不适用,这是我的理解。 -
@paiv 是的,上面的代码显示没有刷新。您知道
shouldRefreshRefetchedObjects确实适用的任何情况吗?
标签: macos core-data macos-mojave