【问题标题】:Cocoa Core Data efficient way to count entitiesCocoa Core Data 计算实体的有效方法
【发布时间】:2010-11-11 04:21:22
【问题描述】:

我阅读了很多关于 Core Data 的内容。但是,什么是对实体类型进行计数的有效方法(就像 SQL 可以使用 SELECT count(1) ...)。现在我刚刚解决了这个任务,用NSFetchedResultsController 选择所有并获取NSArray 的计数!我确信这不是最好的方法......

【问题讨论】:

    标签: objective-c core-data


    【解决方案1】:

    我不知道使用 NSFetchedResultsController 是否是实现目标的最有效方法(但它可能是)。获取实体实例计数的显式代码如下:

    // assuming NSManagedObjectContext *moc
    
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:[NSEntityDescription entityForName:entityName inManagedObjectContext:moc]];
    
    [request setIncludesSubentities:NO]; //Omit subentities. Default is YES (i.e. include subentities)
    
    NSError *err;
    NSUInteger count = [moc countForFetchRequest:request error:&err];
    if(count == NSNotFound) {
      //Handle error
    }
    
    [request release];
    

    【讨论】:

    • 在 Leopard 上你想使用 countForFetchRequest: 而不是 executeFetchRequest:
    • 并跳过设置谓词。无谓词:获取所有符合实体描述的对象
    • 仅供参考,如果特定请求没有结果,则count == 0,NSNotFound = NSIntegerMax,因此如果没有结果,将不会执行'//Handel error'。
    • setIncludesSubentities 上有错字吗?我认为文档在“实体”中表示小写“e”,而不是示例代码中的大写“E”。
    • @LarsSchneider 的文档 countForFetchRequest:error: 声明 NSNotFound 在出现错误时返回。一般来说,Cocoa 约定中的NSError 处理是如果没有错误发生,err 的值是未定义的(并且通常是危险的)。
    【解决方案2】:

    需要明确的是,您计算的不是实体,而是特定实体的实例。 (要从字面上计算实体,请向托管对象模型询问其实体的数量。)

    要在不获取所有数据的情况下计算给定实体的所有实例,请使用-countForFetchRequest:

    例如:

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity: [NSEntityDescription entityForName: entityName inManagedObjectContext: context]];
    
    NSError *error = nil;
    NSUInteger count = [context countForFetchRequest: request error: &error];
    
    [request release];
    
    return count;
    

    【讨论】:

      【解决方案3】:

      斯威夫特

      在 Core Data 中计算实体实例的总数相当容易:

      let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
      let fetchRequest = NSFetchRequest(entityName: "MyEntity")
      let count = context.countForFetchRequest(fetchRequest, error: nil)
      

      我在模拟器中用超过 400,000 个对象进行了测试,结果相当快(虽然不是瞬时的)。

      【讨论】:

        【解决方案4】:

        我将添加它以使其更加高效...并且因为它只是一个计数,您实际上并不需要任何属性值,当然就像上面的代码示例之一一样,您不需要 sub-实体。

        所以,代码应该是这样的:

        int entityCount = 0;
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"YourEntity" inManagedObjectContext:_managedObjectContext];
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        [fetchRequest setEntity:entity];
        [fetchRequest setIncludesPropertyValues:NO];
        [fetchRequest setIncludesSubentities:NO];
        NSError *error = nil;
        NSUInteger count = [_managedObjectContext countForFetchRequest: fetchRequest error: &error];
        if(error == nil){
            entityCount = count;
        }
        

        希望对你有帮助。

        【讨论】:

          【解决方案5】:

          我认为对对象进行计数最简单、最有效的方法是将NSFetchRequest 结果类型设置为NSCountResultType 并使用NSManagedObjectContext countForFetchRequest:error: 方法执行。

          NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:entityName];
          fetchRequest.resultType = NSCountResultType;
          NSError *fetchError = nil;
          NSUInteger itemsCount = [managedObjectContext countForFetchRequest:fetchRequest error:&fetchError];
          if (itemsCount == NSNotFound) {
              NSLog(@"Fetch error: %@", fetchError);
          }
          
          // use itemsCount
          

          【讨论】:

            【解决方案6】:

            我为 Swift 3 编写了一个简单的实用方法来获取对象的数量。

            static func fetchCountFor(entityName: String, predicate: NSPredicate, onMoc moc: NSManagedObjectContext) -> Int {
            
                var count: Int = 0
            
                moc.performAndWait {
            
                    let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: entityName)
                    fetchRequest.predicate = predicate
                    fetchRequest.resultType = NSFetchRequestResultType.countResultType
            
                    do {
                        count = try moc.count(for: fetchRequest)
                    } catch {
                        //Assert or handle exception gracefully
                    }
            
                }
            
                return count
            }
            

            【讨论】:

              【解决方案7】:

              在 Swift 3 中

                static func getProductCount() -> Int {
                  let moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
                  let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Product")
                  let count = try! moc.count(for: fetchRequest)
                  return count
              }
              

              【讨论】:

                【解决方案8】:

                其实就是这样:

                let kBoat = try? yourContainer.viewContext.count(for: NSFetchRequest(entityName: "Boat"))
                

                “船”只是数据模型屏幕中实体的名称:

                什么是全局yourContainer

                要在应用中的某个时间点使用核心数据,只需一次,您只需执行一次

                var yourContainer = NSPersistentContainer(name: "stuff")
                

                其中“stuff”只是数据模型文件的名称。

                你只需要一个单例,

                import CoreData
                public let core = Core.shared
                public final class Core {
                    static let shared = Core()
                    var container: NSPersistentContainer!
                    private init() {
                        container = NSPersistentContainer(name: "stuff")
                        container.loadPersistentStores { storeDescription, error in
                            if let error = error { print("Error loading... \(error)") }
                        }
                    }
                    
                    func saveContext() {
                        if container.viewContext.hasChanges {
                            do { try container.viewContext.save()
                            } catch { print("Error saving... \(error)") }
                        }
                    }
                }
                

                所以从应用程序的任何地方

                core.container
                

                是你的容器,

                所以在实践中要获得任何实体的计数,它只是

                let k = try? core.container.viewContext.count(for: NSFetchRequest(entityName: "Boat"))
                

                【讨论】:

                  【解决方案9】:

                  如果您想查找特定谓词提取的计数,我相信这是最好的方法:

                  NSError *err;
                  NSUInteger count = [context countForFetchRequest:fetch error:&err];
                  
                  if(count > 0) {
                  NSLog(@"EXIST"); 
                  } else {
                  NSLog(@"NOT exist");
                  }
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2021-10-03
                    • 1970-01-01
                    • 2012-05-28
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2016-08-14
                    相关资源
                    最近更新 更多