在Core Data中使用NSPredicate过滤setPropertiesToFetch?

时间:2010-08-27 15:14:19

标签: iphone objective-c core-data

我有一个视图,我希望获得“百分比”属性的平均值,而无需将所有对象(及其他属性)从Core Data加载到内存中。我已经在Apple的文档中找到了如何做到这一点,但问题是我想将平均百分比的对象限制为另一个名为“numberAsked”的属性大于0的对象。我认为这是我可以做的事情与NSPredicate。

这就是我所拥有的:

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

NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:@"numberAsked > 0"];
[request setPredicate:searchPredicate];

[request setResultType:NSDictionaryResultType];


NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"percentCorrect"];
NSExpression *averagePercentExpression = [NSExpression expressionForFunction:@"average:"
                                                                   arguments:[NSArray arrayWithObject:keyPathExpression]];

NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:@"averagePercentageCorrect"];
[expressionDescription setExpression:averagePercentExpression];
[expressionDescription setExpressionResultType:NSDecimalAttributeType];

[request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];

NSError *error;
NSArray *objects = [managedObjectContext executeFetchRequest:request error:&error];

它发生的事情似乎是获取所有对象并忽略NSPredicate。我不知道更改请求的结果类型是否对此做了什么,或者我需要使用另一个NSExpression过滤对象,或者是什么。

我的测试值是现在所有对象都将numberAsked属性设置为0,所以理论上我的最终对象数组的计数应为0,从中我指定百分比为“N / A”。但事情并没有发生。

我感谢任何帮助!

1 个答案:

答案 0 :(得分:2)

您无法将表达式传递给setPropertiesToFetch:。它需要一组NSPropertyDescription个对象。我有点惊讶它并没有崩溃。

你想要这样的东西:

NSManagedObject *mo;
for (int i=0; i<5; i++) {
    mo=[NSEntityDescription insertNewObjectForEntityForName:@"Test" inManagedObjectContext:self.moc];
    [mo setValue:[NSNumber numberWithInt:i] forKey:@"numAttrib" ];      
}
[self saveContext];
NSFetchRequest *fetch=[[NSFetchRequest alloc] init];
NSEntityDescription *testEntity=[NSEntityDescription entityForName:@"Test" inManagedObjectContext:self.moc];
[fetch setEntity:testEntity]; 
NSDictionary *propDict=[testEntity propertiesByName];
[fetch setPropertiesToFetch:[NSArray arrayWithObject:[propDict valueForKey:@"numAttrib"]]];
NSArray *fetchReturn=[self performFetch:fetch];//<-- my custom boilerplate
NSLog(@"fetchReturn=%@",fetchReturn);
id theAvg=[fetchReturn valueForKeyPath:@"@avg.numAttrib"];
NSLog(@"theAvg=%f",[theAvg floatValue]);

...打印:

fetchReturn=(
    "<NSManagedObject: 0x5d2fae0> (entity: Test; id: 0x5d0c310 <x-coredata://384EFAF2-1921-4CB0-85B2-402DBA145615/Test/p1> ; data: {\n    numAttrib = 3;\n})",
    "<NSManagedObject: 0x5d35df0> (entity: Test; id: 0x5d34480 <x-coredata://384EFAF2-1921-4CB0-85B2-402DBA145615/Test/p2> ; data: {\n    numAttrib = 1;\n})",
    "<NSManagedObject: 0x5d33890> (entity: Test; id: 0x5d31810 <x-coredata://384EFAF2-1921-4CB0-85B2-402DBA145615/Test/p3> ; data: {\n    numAttrib = 2;\n})",
    "<NSManagedObject: 0x5d36d10> (entity: Test; id: 0x5d0dfa0 <x-coredata://384EFAF2-1921-4CB0-85B2-402DBA145615/Test/p4> ; data: {\n    numAttrib = 4;\n})",
    "<NSManagedObject: 0x5d38f00> (entity: Test; id: 0x5d302a0 <x-coredata://384EFAF2-1921-4CB0-85B2-402DBA145615/Test/p5> ; data: {\n    numAttrib = 0;\n})"
)
theAvg=2.000000

如果你想减轻重量。您可以添加:

[fetch setResultType:NSDictionaryResultType];

...返回一个单键字典数组,如下所示:

fetchReturn=(
        {
        numAttrib = 2;
    },
        {
        numAttrib = 0;
    },
        {
        numAttrib = 4;
    },
        {
        numAttrib = 1;
    },
        {
        numAttrib = 3;
    }
)
float=2.000000