2009-12-18 16 views
15

Necesito averiguar el valor máximo de un atributo de una entidad de datos central.Cálculo del valor máximo para un atributo de datos centrales - NSCFNumber error

Todavía estoy firmemente en la curva de aprendizaje de Cocoa, y esta es una aplicación de prueba simple que estoy usando para aprender.

La aplicación importa fortunas de un archivo de texto y muestra una tabla en la pantalla. Las importaciones se realizan en un hilo de fondo separado.

me encontré con este código en línea, que he tratado de conseguir trabajo:

- (double)getMaxID 
{ 
    NSLog(@"in getMaxID"); // debug 

    // Use a new moc with the original persistentStoreCoordinator to ensure thread safety 
    NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init]; 
    [moc setPersistentStoreCoordinator:[[self delegate] persistentStoreCoordinator]]; 

    // Create fetch 
    NSFetchRequest *fetch = [[NSFetchRequest alloc] init]; 
    [fetch setEntity:[NSEntityDescription entityForName:@"Fortune" inManagedObjectContext:moc]]; 
    [fetch setResultType:NSDictionaryResultType]; 

    // Expression for Max ID 
    NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"id"]; 
    NSExpression *minExpression = [NSExpression expressionForFunction:@"max:" arguments: [NSArray arrayWithObject:keyPathExpression]]; 
    NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init]; 
    [expressionDescription setName:@"maxID"]; 
    [expressionDescription setExpression:minExpression]; 
    [expressionDescription setExpressionResultType:NSDoubleAttributeType]; 
    [fetch setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]]; 

    // Execute the fetch. 
    double theID = 0; 
    NSError *error = nil; 
    NSArray *objects = nil; 
    objects = [moc executeFetchRequest:fetch error:&error]; // crashes here 

    if (objects && ([objects count] > 0)) 
    { 
     NSLog(@"query successful"); // debug 
     theID = [((NSNumber *)[[objects objectAtIndex:0] valueForKey:@"maxID"]) doubleValue]; 
    } 
    else 
    { 
     NSLog(@"Setting default value for theID"); // debug 
     theID = 0; 
    } 

    return(theID); 
} 

Mi entidad es llamada "Fortuna" y el atributo se llama "id" (un doble).

Cuando se ejecuta el código, falla cuando se ejecuta la solicitud de búsqueda. La consola muestra esto:

 
2009-12-18 00:53:42.777 FortunesHelperMVC[4027:1703] -[NSCFNumber count]: unrecognized selector sent to instance 0x1004d7b10 
2009-12-18 00:53:42.778 FortunesHelperMVC[4027:1703] An uncaught exception was raised 
2009-12-18 00:53:42.778 FortunesHelperMVC[4027:1703] -[NSCFNumber count]: unrecognized selector sent to instance 0x1004d7b10 
2009-12-18 00:53:42.779 FortunesHelperMVC[4027:1703] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFNumber count]: unrecognized selector sent to instance 0x1004d7b10' 
*** Call stack at first throw: 
(
0 CoreFoundation 0x00007fff83ed9444 __exceptionPreprocess + 180 
1 libobjc.A.dylib 0x00007fff85fbb0f3 objc_exception_throw + 45 
2 CoreFoundation 0x00007fff83f321c0 +[NSObject(NSObject) doesNotRecognizeSelector:] + 0 
3 CoreFoundation 0x00007fff83eac08f ___forwarding___ + 751 
4 CoreFoundation 0x00007fff83ea81d8 _CF_forwarding_prep_0 + 232 
5 Foundation 0x00007fff88a5609e +[_NSPredicateUtilities max:] + 46 
6 Foundation 0x00007fff8893ce72 -[NSFunctionExpression expressionValueWithObject:context:] + 530 
7 CoreData 0x00007fff8613b5b1 -[NSMappedObjectStore executeFetchRequest:withContext:] + 2081 
8 CoreData 0x00007fff8613ad10 -[NSMappedObjectStore executeRequest:withContext:] + 80 
9 CoreData 0x00007fff86108900 -[NSPersistentStoreCoordinator(_NSInternalMethods) executeRequest:withContext:] + 688 
10 CoreData 0x00007fff8610621b -[NSManagedObjectContext executeFetchRequest:error:] + 267 
11 FortunesHelperMVC 0x0000000100001d9d -[ImportOperation getMaxID] + 572 
12 FortunesHelperMVC 0x0000000100001f95 -[ImportOperation main] + 330 
13 Foundation 0x00007fff888f406d -[__NSOperationInternal start] + 681 
14 Foundation 0x00007fff888f3d23 ____startOperations_block_invoke_2 + 99 
15 libSystem.B.dylib 0x00007fff86a98ce8 _dispatch_call_block_and_release + 15 
16 libSystem.B.dylib 0x00007fff86a77279 _dispatch_worker_thread2 + 231 
17 libSystem.B.dylib 0x00007fff86a76bb8 _pthread_wqthread + 353 
18 libSystem.B.dylib 0x00007fff86a76a55 start_wqthread + 13 
) 
terminate called after throwing an instance of 'NSException' 

¿Alguna idea de por qué esto no está funcionando? Estoy perplejo después de mucho googlear.

Gracias

Darren.

Respuesta

2

El problema era que esta línea está mal:

[fetch setResultType:NSDictionaryResultType]; 

El tipo de resultado debería haber sido NSManagedObjectResultType

Saludos

Darren.

+1

Pero no que acaba de terminar volviendo todas las entidades de ese tipo (sin pasar por el NSExpressionDescription configura? En otras palabras, que no cause una ruptura, pero no termina recibiendo la propiedad que estabas buscando, ¿verdad? – Dov

15

que tuvieron que resolver un problema similar y se acercó un poco diferente por:

  • consulta de la entidad
  • pedido por el atributo que desea
  • limitar los resultados traiga a 1

El código para esto está a continuación. Estoy consultando una entidad llamada 'entityName' y recuperando el valor máximo para el atributo 'sequenceId'.

NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
NSEntityDescription *res = [NSEntityDescription entityForName:@"entityName" inManagedObjectContext:managedObjectContext]; 
[request setEntity:res]; 

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"sequenceId" ascending:NO]; 
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; 
[request setSortDescriptors:sortDescriptors]; 
[sortDescriptors release]; 
[sortDescriptor release]; 

[request setFetchLimit:1]; 

NSError *error = nil; 
NSArray *results = [managedObjectContext executeFetchRequest:request error:&error]; 
[request release]; 
if (results == nil) { 
    NSLog(@"error fetching the results: %@",error); 
} 

NSInteger maximumValue = 0; 
if (results.count == 1) { 
    Result *result = (Result*)[results objectAtIndex:0]; 
    maximumValue = [result.sequenceId integerValue]; 
} 
+0

Cuando traté de hacer lo que dijiste, estoy obteniendo esto como resultado. Supongo que está dando el límite máximo de tipo Int32. "account_id" = 139784529; – Harish

+2

Al menos en iOS 6 e iOS 7, el tiempo de clasificación crece linealmente con el número de objetos en la base de datos. Mala idea. – Christoph

10

Este código de Core Data Programming Guide debería funcionar.

NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:context]; 
[request setEntity:entity]; 

// Specify that the request should return dictionaries. 
[request setResultType:NSDictionaryResultType]; 

// Create an expression for the key path. 
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"creationDate"]; 

// Create an expression to represent the maximum value at the key path 'creationDate' 
NSExpression *maxExpression = [NSExpression expressionForFunction:@"max:" arguments:[NSArray arrayWithObject:keyPathExpression]]; 

// Create an expression description using the maxExpression and returning a date. 
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init]; 

// The name is the key that will be used in the dictionary for the return value. 
[expressionDescription setName:@"maxDate"]; 
[expressionDescription setExpression:maxExpression]; 
[expressionDescription setExpressionResultType:NSDateAttributeType]; 

// Set the request's properties to fetch just the property represented by the expressions. 
[request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]]; 

// Execute the fetch. 
NSError *error = nil; 
NSArray *objects = [managedObjectContext executeFetchRequest:request error:&error]; 
if (objects == nil) { 
    // Handle the error. 
} 
else { 
    if ([objects count] > 0) { 
     NSLog(@"Maximum date: %@", [[objects objectAtIndex:0] valueForKey:@"maxDate"]); 
    } 
} 
+0

También agregaría este enlace a un gran artículo: http://useyourloaf.com/blog/2012/01/19 /core-data-queries-using-expressions.html –

Cuestiones relacionadas