集合函数上的iOS FetchRequest:如何包含挂起的更改?
我终于至less缩小了这个问题。 我正在计算一些支出的总和函数(在这个例子中是总和)。 如果我改变了一些支出,这个聚集提取不会立即刷新,而只是在一段时间之后(可能在更改被保存到数据库之后)。 我在文档中find了这个部分:
- (void)setIncludesPendingChanges:(BOOL)yesNo
根据文件
结果types
NSDictionaryResultType
不支持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议的原始循环更快。
这是一个更简洁和美观的代码,但绝不会更快。 我可以立即看到几个原因(费用)。
- 从文本格式创build和编译一个谓词需要时间和内存(几个分配)
- 使用谓词重新筛选self.hasExpenditures分配并启动一个新的NSSet(shortSet),并使用(保留的)对匹配支出(date范围)的引用来填充它。 为此,它必须循环扫描一个接一个的自我支出。
- 然后,最后的总计算再次循环遍历子集上的总和,并分配最终的NSNumber对象。
在循环版本中,没有新的分配,没有保留也没有释放任何东西,只有一个通过self.expenditures设置。
总而言之,我的观点是,第二个实现将至less需要完成这个循环的内容,再加上更多的开销。
最后一点:因为id中的collection可以同时使用GCD在几个项目上运行,所以速度相当快。
我认为你至less应该通过广泛的性能testing来匹配这些替代品。
- 数组索引超出范围 – 可select解除绑定时出错
- CoreData,UIManagedDocument和空的持久存储
- 核心数据,当NSFetchRequest返回NSDictionaryResultType时如何获取NSManagedObject的ObjectId?
- 如何检查UICollectionView中插入和删除的项目,看到意外的删除项目
- iOS 4核心数据…多任务的变化?
- 家长MOC获取来自儿童MOC的空数据的变化
- 是否有可能按“NSFetchRequest”中的子类进行sorting而不添加其他属性?
- 找不到类,使用默认的NSManagedObject来代替
- 应用程序拒绝在persistenstore创build崩溃