核心数据 - 使用同一字段获取所有实体

Posted

技术标签:

【中文标题】核心数据 - 使用同一字段获取所有实体【英文标题】: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"))
.
.
.

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

【问题讨论】:

【参考方案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)
            ...
        
    

【讨论】:

以上是关于核心数据 - 使用同一字段获取所有实体的主要内容,如果未能解决你的问题,请参考以下文章

如何在核心数据iOS中获取每个实体的最后一个条目

获取所有核心数据子实体

核心数据:获取特定对象的多对多关系中的所有实体?

如何从核心数据中获取父实体的所有子实体,以及如何将父数据用作 UITableview

使用核心数据swift ios将实体的所有属性获取到tableview中的行中的标签

获取核心数据实体,但不获取子实体