Вычисление максимального значения для атрибута данных ядра - ошибка NSCFNumber
Мне нужно узнать максимальное значение атрибута основного объекта данных.
Я все еще твердо придерживаюсь кривой обучения Cocoa, и это простое тестовое приложение, которое я использую для изучения.
Приложение импортирует состояние из текстового файла и отображает таблицу на экране. Импорт выполняется в отдельном фоновом потоке.
Я нашел этот код в Интернете, который я попытался получить:
- (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);
}
Моя сущность называется "Fortune", а атрибут называется "id" (a Double).
Когда код запускается, он сбой, когда выполняется запрос на выборку. Консоль показывает это:
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'
Любые идеи, почему это не работает? Я сильно разочаровываюсь после того, как много гуглингов.
Спасибо
Даррен.
Ответы
Ответ 1
Мне пришлось решить подобную проблему и подошел немного по-другому:
- запрос объекта
- упорядочение по атрибуту, который вы хотите
- ограничить результаты выборки до 1
Код для этого ниже. Я запрашиваю объект под названием "имя_объекта" и извлекаю максимальное значение для атрибута "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];
}
Ответ 2
Этот код из Руководство по программированию основных данных должен работать.
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 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"]);
}
}
Ответ 3
Проблема в том, что эта строка неверна:
[fetch setResultType:NSDictionaryResultType];
Тип результата должен быть NSManagedObjectResultType
Привет
Даррен.