集合函数上的iOS FetchRequest:如何包含挂起的更改?

我终于至less缩小了这个问题。 我正在计算一些支出的总和函数(在这个例子中是总和)。 如果我改变了一些支出,这个聚集提取不会立即刷新,而只是在一段时间之后(可能在更改被保存到数据库之后)。 我在文档中find了这个部分:

- (void)setIncludesPendingChanges:(BOOL)yesNo 

根据文件

结果typesNSDictionaryResultType不支持YES值,包括计算聚合结果(如max和min)。 对于字典,从读取中返回的数组反映了持久性存储中的当前状态,并且不考虑上下文中的任何挂起的更改,插入或删除。 如果您需要为最大和最小等简单聚合考虑待处理的更改,则可以改为使用正常的获取请求,按照所需的属性进行sorting,获取限制为1。

好的,我怎么能仍然包括未决的变化? 我正在使用NSFetchedResultsController来显示我的数据。 这里是我的聚合函数:

 - (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]; } } } 

编辑: * 通过NSSet循环是否可能和足够快? *

 - (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]; } 

编辑终于有了答案 Thx给你们所有我终于find了循环中的问题。 这工作非常快,很好:

 - (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调用。

这足够今天.. 🙂

你的解决scheme是可以的,但是你仍然可以通过首先缩短集合,然后通过利用KVC来避免循环来加快速度并产生更短的代码:

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

我不确定使用谓词来过滤一个子集是从事先build议的原始循环更快。

这是一个更简洁和美观的代码,但绝不会更快。 我可以立即看到几个原因(费用)。

  1. 从文本格式创build和编译一个谓词需要时间和内存(几个分配)
  2. 使用谓词重新筛选self.hasExpenditures分配并启动一个新的NSSet(shortSet),并使用(保留的)对匹配支出(date范围)的引用来填充它。 为此,它必须循​​环扫描一个接一个的自我支出。
  3. 然后,最后的总计算再次循环遍历子集上的总和,并分配最终的NSNumber对象。

在循环版本中,没有新的分配,没有保留也没有释放任何东西,只有一个通过self.expenditures设置。

总而言之,我的观点是,第二个实现将至less需要完成这个循环的内容,再加上更多的开销。

最后一点:因为id中的collection可以同时使用GCD在几个项目上运行,所以速度相当快。

我认为你至less应该通过广泛的性能testing来匹配这些替代品。