使用CoreData执行乘法(聚合):如何? [英] Performing multiplication (aggregation) with CoreData: how to?

查看:105
本文介绍了使用CoreData执行乘法(聚合):如何?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Jeff Lamarche的精彩教程之后,我尝试汇总 NSManagedObject 的特定子类的数据。



这是场景。我创建了一个名为 Product 的类,它扩展了 NSManagedObject 类。 产品类有三个属性,如下所示:

  @property ,retain)NSString * name; 
@property(nonatomic,retain)NSNumber * quantity;
@property(nonatomic,retain)NSNumber * price;

我还创建了一个类别,名为 Product + Aggregate ,其中I执行和聚合。特别是,在Jeff教程之后,我管理了quantity属性的总和。

  +(NSNumber *)aggregateOperation:函数onAttribute:(NSString *)attributeName withPredicate:(NSPredicate *)predicate inManagedObjectContext:(NSManagedObjectContext *)context 
{
NSString * className = NSStringFromClass([self class]);

NSExpression * ex = [NSExpression expressionForFunction:function
arguments:[NSArray arrayWithObject:[NSExpression expressionForKeyPath:attributeName]]];

NSExpressionDescription * ed = [[NSExpressionDescription alloc] init];
[ed setName:@result];
[ed setExpression:ex];
[ed setExpressionResultType:NSInteger64AttributeType];

NSArray * properties = [NSArray arrayWithObject:ed];
[ed release];

NSFetchRequest * request = [[NSFetchRequest alloc] init];
[request setPropertiesToFetch:properties];
[request setResultType:NSDictionaryResultType];

if(predicate!= nil)
[request setPredicate:predicate];

NSEntityDescription * entity = [NSEntityDescription entityForName:className
inManagedObjectContext:context];
[request setEntity:entity];

NSArray * results = [context executeFetchRequest:request error:nil];
NSDictionary * resultsDictionary = [results objectAtIndex:0];
NSNumber * resultValue = [resultDictionary objectForKey:@result];

return resultValue;
}

这个类方法从特定 UIViewController

  NSNumber * totalQuantity = [product aggregateOperation:@sum:onAttribute:@数量withPredicate:nil inManagedObjectContext:self.context]; 

代码运行良好。事实上,如果我说3个产品

  NAME QUANTITY PRICE 
产品1 2 23.00
产品2 4 12.00
PRODUCT 3 1 2.00

aggregateOperation 方法按预期返回7。



现在我再多一个步骤。修改该方法后,我需要返回产品订单的总成本。换句话说,我需要为每个产品计算QUANTITY * PRICE值,最后返回TOTAL。



你能建议我正确的方法吗?

这是Cyber​​fox建议之后使用的新代码,但很遗憾,它不起作用。

  NSString * className = NSStringFromClass([self class]); 

NSArray * quantityPrice = [NSArray arrayWithObjects:[NSExpression expressionForKeyPath:@quantity],[NSExpression expressionForKeyPath:@price],nil];

NSArray * multiplyExpression = [NSArray arrayWithObject:[NSExpression expressionForFunction:@multiply:by:arguments:quantityPrice]];

NSExpression * ex = [NSExpression expressionForFunction:function arguments:multiplyExpression];

NSExpressionDescription * ed = [[NSExpressionDescription alloc] init];
[ed setName:@result];
[ed setExpression:ex];
[ed setExpressionResultType:NSInteger64AttributeType];

//与之前相同


解决方案



以下是代码:

  static NSString * exprName1 = @val1; 
static NSString * exprName2 = @val2;

NSString * className = NSStringFromClass([self class]);

NSExpression * quantityPathExpression = [NSExpression expressionForKeyPath:firstAttribute]; //例如。 quantity
NSExpression * unitaryPricePathExpression = [NSExpression expressionForKeyPath:secondAttribute]; //例如。价格

NSExpressionDescription * quantityED = [[NSExpressionDescription alloc] init];
[quantityED setName:exprName1];
[quantityED setExpression:quantityPathExpression];
[quantityED setExpressionResultType:NSDictionaryResultType];

NSExpressionDescription * unitaryPriceED = [[NSExpressionDescription alloc] init];
[unitaryPriceED setName:exprName2];
[unitaryPriceED setExpression:unitaryPricePathExpression];
[unitaryPriceED setExpressionResultType:NSDictionaryResultType];

NSArray * properties = [NSArray arrayWithObjects:quantityED,unitaryPriceED,nil];
[quantityED release];
[unitaryPriceED release];

NSFetchRequest * request = [[NSFetchRequest alloc] init];
[request setPropertiesToFetch:properties];
[request setResultType:NSDictionaryResultType];

if(predicate!= nil)
[request setPredicate:predicate];

NSEntityDescription * entity = [NSEntityDescription entityForName:className inManagedObjectContext:context];
[request setEntity:entity];

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

if(error!= nil)
{
NSLog(@发生错误:%@,[error localizedDescription]);
abort();
}

float total = 0;
for(NSDictionary * resultDict in results)
{
NSNumber * quantityNumber = [resultDict valueForKey:exprName1];
NSNumber * unitaryPriceNumber = [resultDict valueForKey:exprName2];

int moltVal = [quantityNumber intValue] * [unitaryPriceNumber intValue];

total + = moltVal;
}

return [NSNumber numberWithInt:total];

PS 使用它创建一个返回 NSNumber 并接受作为参数的托管上下文和要在其中执行数据检索的2个属性( NSString )。



希望它有帮助!


Following a fantastic tutorial by Jeff Lamarche, I'm trying to aggregate data for a specific subclass of NSManagedObject.

This is the scenario. I created a class named Product that extends NSManagedObject class. Product class has three properties like the following:

@property (nonatomic, retain) NSString* name;
@property (nonatomic, retain) NSNumber* quantity;
@property (nonatomic, retain) NSNumber* price;

I also created a category, called Product+Aggregate, where I perform a sum aggregation. In particular, following Jeff tutorial, I managed the sum for quantity attribute.

+(NSNumber *)aggregateOperation:(NSString *)function onAttribute:(NSString *)attributeName withPredicate:(NSPredicate *)predicate inManagedObjectContext:(NSManagedObjectContext *)context
{
    NSString* className = NSStringFromClass([self class]);

    NSExpression *ex = [NSExpression expressionForFunction:function 
        arguments:[NSArray arrayWithObject:[NSExpression expressionForKeyPath:attributeName]]];

    NSExpressionDescription *ed = [[NSExpressionDescription alloc] init];
    [ed setName:@"result"];
    [ed setExpression:ex];
    [ed setExpressionResultType:NSInteger64AttributeType];

    NSArray *properties = [NSArray arrayWithObject:ed];
    [ed release];

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setPropertiesToFetch:properties];
    [request setResultType:NSDictionaryResultType];

    if (predicate != nil)
        [request setPredicate:predicate];

    NSEntityDescription *entity = [NSEntityDescription entityForName:className
        inManagedObjectContext:context];
    [request setEntity:entity];

    NSArray *results = [context executeFetchRequest:request error:nil];
    NSDictionary *resultsDictionary = [results objectAtIndex:0];
    NSNumber *resultValue = [resultsDictionary objectForKey:@"result"];

    return resultValue;
}

This class method is called as follow from a specific UIViewController:

NSNumber *totalQuantity = [Product aggregateOperation:@"sum:" onAttribute:@"quantity" withPredicate:nil inManagedObjectContext:self.context];

The code works well. In fact, if I have say 3 product

NAME         QUANTITY      PRICE
PRODUCT 1    2             23.00 
PRODUCT 2    4             12.00
PRODUCT 3    1             2.00

The aggregateOperation method returns 7 as expected.

Now I would have one more step. Modifying that method, I need to return the total cost for product order. In other words, I need to calculate QUANTITY*PRICE value for each product and finally return the TOTAL.

Could you suggest me the right way? Thank you in advance.

EDIT This is the new code I use after Cyberfox suggestion but unfortunately it doesn't work.

NSString* className = NSStringFromClass([self class]);

NSArray *quantityPrice = [NSArray arrayWithObjects: [NSExpression expressionForKeyPath:@"quantity"], [NSExpression expressionForKeyPath:@"price"], nil];

NSArray *multiplyExpression = [NSArray arrayWithObject:[NSExpression expressionForFunction:@"multiply:by:" arguments:quantityPrice]];

NSExpression *ex = [NSExpression expressionForFunction:function arguments:multiplyExpression];

NSExpressionDescription *ed = [[NSExpressionDescription alloc] init];
[ed setName:@"result"];
[ed setExpression:ex];
[ed setExpressionResultType:NSInteger64AttributeType];

// same as before

解决方案

For those interested in, I found the solution for the problem above.

Here's the code:

static NSString* exprName1 = @"val1";
static NSString* exprName2 = @"val2";

NSString *className = NSStringFromClass([self class]); 

NSExpression *quantityPathExpression = [NSExpression expressionForKeyPath:firstAttribute]; //e.g. quantity    
NSExpression *unitaryPricePathExpression = [NSExpression expressionForKeyPath:secondAttribute]; //e.g. price

NSExpressionDescription *quantityED = [[NSExpressionDescription alloc] init];
[quantityED setName:exprName1];
[quantityED setExpression:quantityPathExpression];
[quantityED setExpressionResultType:NSDictionaryResultType];    

NSExpressionDescription *unitaryPriceED = [[NSExpressionDescription alloc] init];
[unitaryPriceED setName:exprName2];
[unitaryPriceED setExpression:unitaryPricePathExpression];
[unitaryPriceED setExpressionResultType:NSDictionaryResultType];

NSArray *properties = [NSArray arrayWithObjects:quantityED, unitaryPriceED, nil];
[quantityED release];
[unitaryPriceED release];

NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setPropertiesToFetch:properties];
[request setResultType:NSDictionaryResultType];

if (predicate != nil)
   [request setPredicate:predicate];

NSEntityDescription *entity = [NSEntityDescription entityForName:className inManagedObjectContext:context];
[request setEntity:entity];

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

if(error != nil)
{
   NSLog(@"An error occurred: %@", [error localizedDescription]);
   abort();
}

float total = 0;
for (NSDictionary *resultDict in results) 
{
   NSNumber* quantityNumber = [resultDict valueForKey:exprName1];
   NSNumber* unitaryPriceNumber = [resultDict valueForKey:exprName2];

   int moltVal = [quantityNumber intValue]*[unitaryPriceNumber intValue];

   total += moltVal;
}    

return [NSNumber numberWithInt:total];

P.S. to use it create a Class method that returns a NSNumber and accepts as parameters the managed context and 2 attributes (NSString) where you want to perform data retrieving.

Hope it helps!

这篇关于使用CoreData执行乘法(聚合):如何?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆