iOS FetchRequest on aggregate functions:如何包括挂起的更改? [英] iOS FetchRequest on aggregate functions: How to include pending changes?

查看:221
本文介绍了iOS FetchRequest on aggregate functions:如何包括挂起的更改?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我终于至少缩小了这个问题。我计算一些聚合函数(如在这个例子中的和)的支出。如果我更改一些支出,此聚合提取不会立即刷新,但只会过一段时间(可能在更改已保存到数据库之后)。我在文档中找到了这个部分:

I've finally at least narrowed down this problem. I'm computing some aggregate functions (as in this example the sum) of expenditures. If I change some expenditures, this aggregate fetch doesn't refresh immediately but only after a while (probably after the changes have been saved to the database). I've found this part in the doc:

- (void)setIncludesPendingChanges:(BOOL)yesNo

根据文档


A与结果类型
NSDictionaryResultType 一起不支持,包括聚合结果的计算
(例如max和min)。对于字典,从
fetch返回的数组反映了持久存储中的当前状态,并且
不会考虑
上下文中的任何挂起的更改,插入或删除。如果您需要将某些
简单聚合(如max和min)的待定更改纳入帐户,则可以使用普通的
fetch请求,并根据所需属性排序,获取限制为
1。

A value of YES is not supported in conjunction with the result type NSDictionaryResultType, including calculation of aggregate results (such as max and min). For dictionaries, the array returned from the fetch reflects the current state in the persistent store, and does not take into account any pending changes, insertions, or deletions in the context. If you need to take pending changes into account for some simple aggregations like max and min, you can instead use a normal fetch request, sorted on the attribute you want, with a fetch limit of 1.

确定如何仍然包括待定更改?我使用 NSFetchedResultsController 显示我的数据。这是我的聚合函数:

Ok how can I still include pending changes? I'm using a NSFetchedResultsController to display my data. And here is my aggregate function:

- (NSNumber *)getExpendituresAmountForCostPeriod:(CostPeriod)costPeriod
{
    NSLog(@"getExpenditures_Start");
    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Expenditures"];
    [fetchRequest setResultType:NSDictionaryResultType];

    NSDate *startDate = [NSDate startDateForCostPeriod:[self getBiggestCostPeriod]];
    fetchRequest.predicate = [NSPredicate predicateWithFormat:@"forSpendingCategory = %@ AND date >= %@", self, startDate];        

    //Define what we want
    NSExpression *keyPathExpression = [NSExpression expressionForKeyPath: @"amount"];
    NSExpression *sumExpression = [NSExpression expressionForFunction: @"sum:"
                                                            arguments: [NSArray arrayWithObject:keyPathExpression]];

    //Defining the result type (name etc.)
    NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
    [expressionDescription setName: @"totalExpenditures"];
    [expressionDescription setExpression: sumExpression];
    [expressionDescription setExpressionResultType: NSDoubleAttributeType];

    // Set the request's properties to fetch just the property represented by the expressions.
    [fetchRequest setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];
    NSLog(@"%@", self.managedObjectContext);

    // Execute the fetch.
    NSError *error = nil;
    NSArray *objects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
    if (objects == nil) {
        return [NSNumber numberWithDouble:0];
    } else {
        if ([objects count] > 0) {
            return [[objects objectAtIndex:0] valueForKey:@"totalExpenditures"];
        } else {
            return [NSNumber numberWithDouble:0];
        }
    }
}

/ strong>
* 是否可以通过 NSSet 循环? *

*Is a loop through the NSSet possible and fast enough?*

- (NSNumber *)getExpendituresAmountForCostPeriod:(CostPeriod)costPeriod
{
    NSDate *startDate = [NSDate startDateForCostPeriod:[self getBiggestCostPeriod]];
    double total = 0;

    for(Expenditures *expenditure in self.hasExpenditures){
        if(expenditure.date >= startDate){
            total = total + [expenditure.amount doubleValue];
        }
    }

    return [NSNumber numberWithDouble:total];
}

EDIT FINALLY WITH ANSWER
Thx对所有的人我终于找到了循环中的问题。这工作非常快速和好:

EDIT FINALLY WITH ANSWER Thx to all of you I've finally found the problem in the loop. This works very fast and nice:

- (NSNumber *)getExpendituresAmountForCostPeriod:(CostPeriod)costPeriod
{
    NSDate *startDate = [NSDate startDateForCostPeriod:[self getBiggestCostPeriod]];
    double total = 0;

    for(Expenditures *expenditure in self.hasExpenditures){
        if([expenditure.date compare: startDate] == NSOrderedDescending){
            total = total + [expenditure.amount doubleValue];
        }
    }

    return [NSNumber numberWithDouble:total];
}

从controllerDidChangeContent调用。

Called from controllerDidChangeContent.

这对今天就足够了: - )

That's enough for today.. :-)

推荐答案

您的解决方案是可以的,产生较短的代码,首先缩短集合,然后通过利用KVC避免循环:

Your solution is OK, but you can still speed things up and produce shorter code by first shortening the set and then avoiding the loop by taking advantage of KVC:

NSSet *shortSet = [self.hasExpenditures filteredSetUsingPredicate:
  [NSPredicate predicateWithFormat:@"date > %@", startDate]];
NSNumber *total = [shortSet valueForKeyPath:@"@sum.amount"];

这篇关于iOS FetchRequest on aggregate functions:如何包括挂起的更改?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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