objective c - revista - Cocoa Core Data manera eficiente de contar entidades
revista ethos (8)
Rápido
Es bastante fácil obtener un recuento de la cantidad total de instancias de una entidad en Core Data:
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "MyEntity")
let count = context.countForFetchRequest(fetchRequest, error: nil)
Probé esto en el simulador con un recuento de más de 400,000 objetos y el resultado fue bastante rápido (aunque no instantáneo).
Leí mucho sobre Core Data ... pero ¿cuál es una forma eficiente de contar un Tipo de Entidad (como SQL puede hacer con el conteo SELECT (1) ...). ¡Ahora acabo de resolver esta tarea seleccionando todo con NSFetchedResultsController
y obteniendo el recuento del NSArray
! Estoy seguro de que esta no es la mejor manera ...
Añadiré eso para que sea aún más eficiente ... y porque es solo un conteo, realmente no necesita ningún valor de propiedad y ciertamente, al igual que uno de los ejemplos de código anteriores, tampoco necesita subentidades.
Entonces, el código debería ser así:
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;
}
Espero eso ayude.
Creo que la manera más fácil y más eficiente de contar objetos es establecer el tipo de resultado NSCountResultType
en NSCountResultType
y ejecutarlo con NSManagedObjectContext countForFetchRequest:error:
method.
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
Escribí un método de utilidad simple para Swift 3 para obtener el recuento de los objetos.
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
}
No sé si usar NSFetchedResultsController es la manera más eficiente de lograr su objetivo (pero puede ser). El código explícito para obtener el recuento de las instancias de la entidad se encuentra a continuación:
// 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];
Para ser claros, no se están contando entidades, sino instancias de una entidad particular. (Para contar literalmente las entidades, solicite al modelo de objetos administrados el recuento de sus entidades).
Para contar todas las instancias de una entidad dada sin obtener todos los datos, el uso -countForFetchRequest:
Por ejemplo:
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;
Si desea encontrar el recuento para la obtención predicada específica, creo que esta es la mejor manera:
NSError *err;
NSUInteger count = [context countForFetchRequest:fetch error:&err];
if(count > 0) {
NSLog(@"EXIST");
} else {
NSLog(@"NOT exist");
}
En 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
}