Chained expressions to perform calculations in Core Data

狂风中的少年 提交于 2019-11-27 21:44:26
Martin R

It seems that "collection" function expressions like @average can only be used with key paths, but not in combination with other general expressions, when used as propertiesToFetch. I do not have a reference for that, but it is a problem that others have noticed also:

So you could proceed in two steps: First execute a fetch request that returns an array with the results of all divisions:

NSExpression *fromCurrencyPathExpression = [NSExpression
                                            expressionForKeyPath:@"eur"];
NSExpression *toCurrencyPathExpression   = [NSExpression
                                            expressionForKeyPath:@"usd"];
NSExpression *divisionExpression = [NSExpression
                                    expressionForFunction:@"divide:by:"
                                    arguments:@[fromCurrencyPathExpression,
                                    toCurrencyPathExpression]];

NSString *expressionName = @"ratio";
NSExpressionDescription *expressionDescription =
[[NSExpressionDescription alloc] init];
expressionDescription.name = expressionName;
expressionDescription.expression = divisionExpression;
expressionDescription.expressionResultType= NSDoubleAttributeType;

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Entity"];

request.propertiesToFetch = @[expressionDescription];
request.resultType = NSDictionaryResultType;

NSError *error;
NSArray *ratios = [context executeFetchRequest:request error:&error];

The result is an array of dictionaries:

(lldb) po ratios
(NSArray *) $0 = 0x00000001001170f0 <_PFArray 0x1001170f0>(
{
    ratio = "0.5454545454545454";
},
{
    ratio = "0.4";
},
{
    ratio = "0.5";
}
)

Also, with the "-com.apple.CoreData.SQLDebug 1" option one can see that the divisions are already executed on the SQLite level:

sql: SELECT  t0.ZEUR /  t0.ZUSD FROM ZENTITY t0

Then you can compute the average of all ratios in memory, using Key-Value Coding:

NSNumber *average = [ratios valueForKeyPath:@"@avg.ratio"];

and the result is

(lldb) po average
(NSNumber *) $0 = 0x000000010012fd60 0.4818181818181818
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!