2013-08-31 70 views
1

我必須做出一個複雜的核心數據獲取請求,但我不知道它是否可以製作。 這是我的情況:只有一個實體(費用)具有這些屬性:謂詞和表達式來獲取複雜的請求核心數據

  • 成本(NSDecimalNumber)
  • 存款(NSDecimalNumber)
  • 類別(的NSString)
  • 付費(布爾值)

請求應該返回3個最昂貴的類別,但這些都是必須遵守的規則:

  • 如果付費== YES,費用成本應加費用類別總
  • 如果付費== NO & &存款> 0,費用存款應該被添加到費用類別總
  • 如果支付== NO,沒有什麼應被添加到費用類別總

使用NSExpression,我可以計算每個類別的總數,但它也包括未付費用的費用。 有沒有辦法做到這一點? 非常感謝!

回答

1

你可以,例如,使用NSFetchRequest

// Build the fetch request 
NSString *entityName = NSStringFromClass([Expense class]); 
NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
request.entity = entity; 

其中僅過濾相關費用:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(paid == YES) OR ((paid == NO) AND (deposit > 0))"]; 
request.predicate = predicate; 

,並總結了成本和depost屬性:

NSExpressionDescription *(^makeExpressionDescription)(NSString *, NSString *) = ^(NSString *keyPath, NSString *name) 
{ 
    // Create an expression for the key path. 
    NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:keyPath]; 

    // Create an expression to represent the function you want to apply 
    NSExpression *totalExpression = [NSExpression expressionForFunction: @"sum:" arguments: @[keyPathExpression]]; 

    NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init]; 

    // The name is the key that will be used in the dictionary for the return value 
    expressionDescription.name = name; 
    expressionDescription.expression = totalExpression; 
    expressionDescription.expressionResultType = NSDecimalAttributeType; 

    return expressionDescription; 
}; 

NSExpressionDescription *totalCostDescription = makeExpressionDescription(@"cost", @"totalCost"); 
NSExpressionDescription *totalDepositDescription = makeExpressionDescription(@"deposit", @"totalDeposit"); 

// Specify that the request should return dictionaries. 
request.resultType = NSDictionaryResultType; 

request.propertiesToFetch = @[categoryDescription, 
           paidDescription, 
           totalCostDescription, 
           totalDepositDescription]; 

並按類別和付費狀態對結果進行分組:

// Get 'category' and 'paid' attribute descriptions 
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName 
               inManagedObjectContext:context]; 
NSDictionary *attributes = [entity attributesByName]; 
NSAttributeDescription *categoryDescription = attributes[@"category"]; 
NSAttributeDescription *paidDescription = attributes[@"paid"]; 

// Group by 'category' and 'paid' attributes 
request.propertiesToGroupBy = @[categoryDescription, paidDescription]; 

你會得到有償和無償的開支總結

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

所有你需要做的是結合(和排序),則:

if (results) { 
    NSMutableDictionary *combined = [NSMutableDictionary dictionary]; 

    for (NSDictionary *result in results) { 
     NSString *category = result[@"category"]; 

     BOOL paid = [result[@"paid"] boolValue]; 

     NSDecimalNumber *total = result[paid ? @"totalCost" : @"totalDeposit"]; 

     NSDecimalNumber *sum = combined[category]; 

     if (sum) { 
      total = [total decimalNumberByAdding:sum]; 
     } 

     combined[category] = total; 
    } 

    NSArray *sortedCategories = [combined keysSortedByValueUsingSelector:@selector(compare:)]; 

    [sortedCategories enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
     NSLog(@"Category %@: %@", obj, combined[obj]); 
    }]; 
} 
else { 
    NSLog(@"Error: %@", error); 
} 
+0

EIK,太感謝你了!這正是我所尋找的,我救了我的一天! ;)它像一個魅力! – matteodv