iOS核心数据,不获取刚刚更新了其关系的实体

hlswsv35  于 2023-04-08  发布在  iOS
关注(0)|答案(1)|浏览(145)

问题:当我获取一个在同一上下文中更新了其关系的实体时,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
   }
}
q35jwt9p

q35jwt9p1#

(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 :(["expenses"])
    ▿ _variant : _Variant
      ▿ object : _BridgeStorage<__RawDictionaryStorage>
        - rawValue : (Opaque Value)

相关问题