问题:当我获取一个在同一上下文中更新了其关系的实体时,fetch-request返回一个nil。
说明:
数据模式:Contact<--->Expense(一对多关系),Contact的“serverId”属性是唯一的,由于一些额外的规则,我不能在Core Data中使用“Constraints”,而是使用以下代码。
现在,当从Web响应中插入一个费用数组时,我有多个费用用于同一联系人。下面的代码返回nil,即使联系人存在于同一上下文中,如果它有更新。
if let entity = Contact.fetch(serverId: serverId, context: context) {
return entity
} else {
return Contact.new(serverId: serverId, context: context)
}
下面是用于支持的调试器日志:
- 服务器id是我们用作 predicate 输入的id。
(lldb) po serverId
55001
- Coredata fetch返回nil
(lldb) po Contact.fetch(serverId: serverId, context: context)
nil
- 上下文已经知道对象,因为它刚刚被更新。你可以看到更新的键是一个关系。
(lldb) po context.updatedObjects.filter { ($0 as? Entity)?.serverId == serverId }.count
1
(lldb) po context.updatedObjects.filter { ($0 as? Entity)?.serverId == serverId }.first?.changedValues().keys
▿ Optional<Keys>
▿ some : Dictionary.Keys(["expenses"])
▿ _variant : _Variant
▿ object : _BridgeStorage<__RawDictionaryStorage>
- rawValue : (Opaque Value)
- 在重置上下文之后获取实体。
(lldb) po context.reset()
0 elements
(lldb) po Contact.fetch(serverId: serverId, context: context)
▿ Optional<Contact>
- some : <Contact: 0x6000015371b0> (entity: Contact; id: 0xe7984dad6d91badc <x-coredata://593D407B-BF00-4923-980E-FDC7BEBD46C1/Contact/p834>; data: <fault>)
添加了其他详细信息:
实体只是一个协议 Package 器,下面是一个简化的代码。
protocol Entity {
var serverId: Int64 { get set }
}
extension Contact: Entity {}
要使用多个“Entity”类型重用的提取实现。
extension Entity {
static func fetch(serverId: Int64, context: NSManagedObjectContext) -> Entity? {
let predicate = NSPredicate(format: "serverId == '\(String(serverId))'")
return context.fetch(Entity.self, predicate: predicate)?.first
}
func fetch<T: NSManagedObject>(_ type: T.Type, predicate: NSPredicate?, sort: [NSSortDescriptor]? = nil) -> [T]? {
let context = self
let request = T.fetchRequest()
if let predicate = predicate {
request.predicate = predicate
}
if let sortDescriptors = sort {
request.sortDescriptors = sortDescriptors
}
var results: [NSFetchRequestResult] = []
do {
results = try context.fetch(request)
} catch {
print("Error with request: \(error)")
}
return results as? [T] ?? []
}
临时修复:通过检查当前上下文中的对象添加
if entity == nil, context.hasChanges == true {
entity = context.updatedObjects.first { ($0 as? Entity)?.serverId == serverId } as? Entity
if entity == nil {
entity = context.insertedObjects.first { ($0 as? Entity)?.serverId == serverId } as? Entity
}
}
1条答案
按热度按时间q35jwt9p1#