【问题标题】:Core Data - Fetch all entities using the same field核心数据 - 使用同一字段获取所有实体
【发布时间】:2017-12-12 11:35:03
【问题描述】:

在我的 ios swift 应用程序中,我有一个使用 Core Data 的数据库。 它有许多实体,所有实体都有一个名为syncStatus 的整数字段。可以是0, 1, or 2

在启动时,我想遍历所有具有syncStatus = 1 的实体并将其更改为0

有没有办法在不单独获取每种类型并对其进行更改的情况下做到这一点?

所以我想要的是:

  • 使用syncStatus = 1 获取ALL 实体
  • Loop 通过他们设置syncStatus = 0

目前我正在一一做:

  • 使用syncStatus = 1获取UserEntities
  • 遍历它们并设置syncStatus = 0
  • 使用syncStatus = 1获取countryEntities
  • 遍历它们并设置syncStatus = 0
  • 对每个实体一个一个地做同样的事情

代码:

let allUsers = context?.fetch(FetchRequest<UserEntity>().filtered(with: "syncStatus", equalTo: "1"))
let allCountries = context?.fetch(FetchRequest<CountryEntity>().filtered(with: "syncStatus", equalTo: "1"))
.
.
.

我只是想找到一个通用的方法,以防以后我们添加另一个实体/表,我们不必回到这段代码并在这里也添加它。

【问题讨论】:

    标签: ios swift core-data


    【解决方案1】:

    首先,获取所有条目并过滤它们比应用谓词要昂贵得多。

    我建议使用带有静态方法的协议扩展。好处是可以直接在类型上调用方法

    protocol SyncStatusResettable
    {
        associatedtype Entity: NSManagedObject = Self
    
        var syncStatus : String {get set}
        static var entityName : String { get }
        static func resetSyncStatus(in context: NSManagedObjectContext) throws
    }
    
    extension SyncStatusResettable where Entity == Self
    {
        static var entityName : String {
            return NSStringFromClass(self).components(separatedBy: ".").last!
        }
    
        static func resetSyncStatus(in context: NSManagedObjectContext) throws
        {
            let request = NSFetchRequest<Entity>(entityName: entityName)
            request.predicate = NSPredicate(format: "syncStatus == 1")
            let items = try context.fetch(request)
            for var item in items { item.syncStatus = "0" }
            if context.hasChanges { try context.save() }
        }
    
    }
    

    要使用它,请为所有NSManagedObject 子类采用SyncStatusResettable 并调用

    do {
        try UserEntity.resetSyncStatus(in: managedObjectContext)
        try CountryEntity.resetSyncStatus(in: managedObjectContext)
    } catch { print(error) }
    

    managedObjectContext 是当前的NSManagedObjectContext 实例

    【讨论】:

    • 真的很喜欢这个答案
    【解决方案2】:

    NSManagedObjectModel 允许您枚举它包含的实体,NSEntityDescription 可以为您提供每个实体的属性。一旦你参考了模型:

    let entitiesWithSync = model.entities.filter {
        $0.properties.contains(where: { $0.name == "syncStatus" })
    }
    

    会给你所有相关的实体。然后,您可以使用此实体列表来驱动更新 - 请注意,如果您在启动时执行此操作,则使用 NSBatchUpdateRequest 会更快。您可以使用上述循环中获得的实体描述创建批量更新请求。

    【讨论】:

      【解决方案3】:

      过去我已经遍历了对象模型中的所有entitiesByName:

      lazy var managedObjectModel: NSManagedObjectModel = {
          let modelUrl = NSBundle.mainBundle().URLForResource("SomeProject", withExtension: "momd")!
          return NSManagedObjectModel(contentsOf: modelUrl)
      }
      
      func updateAllData() {
          let appDelegate = UIApplication.shared.delegate as! AppDelegate
          let context = appDelegate.persistentContainer.viewContext
      
          context.performAndWait {
              let allEntities = self.managedObjectModel.entitiesByName
              for (entity, items) in allEntities {
                  let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entity)
                  ...
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-06-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-14
        • 1970-01-01
        相关资源
        最近更新 更多