在获取请求中显示不同的结果,按属性分组并计算该属性的总计

时间:2012-11-17 03:40:04

标签: objective-c core-data nspredicate nsfetchedresultscontroller nsfetchrequest

情景:

我有跟踪iOS应用程序的费用,我有一个名为“DashBoardViewController”的视图控制器(表格视图控制器 - 带FRC),它基本上将我的费用/收入分类给定的一周,一个月或一年,并显示为例如:节目标题:(2012年10月1日至10月7日),它显示了根据特定周或月或年的费用/收入ROWS和相关资料。

我的问题:

我想要完成的是:

假设我在三个不同的日期(分别为11 nov,14 nov,16 nov,2012)分别保存3个名为“Auto”的SAME类别的新费用。

在我的视图控制器中,我想在表格视图中将该类别“自动”显示为一行,但它应该仅显示为一行而不是三次,因为我保存了三个费用(类别为“自动”)和总数对于我保存的所有3项费用(对于该特定类别),应加上金额。类似于以下截图。

enter image description here

我写了一些代码,它给了我相同类别的三条而不是我真正想要的东西(同一类别的一行),我不知道如何计算它们的总数?应该是与NSPredicate相关的东西或取得的结果控制器。 任何帮助都将受到高度赞赏。

- (void)userDidSelectStartDate:(NSDate *)startDate andEndDate:(NSDate *)endDate
{
    AppDelegate * applicationDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
    NSManagedObjectContext * context = [applicationDelegate managedObjectContext];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
  // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Money" inManagedObjectContext:context];
   [fetchRequest setEntity:entity];

  // Set the batch size to a suitable number.
   [fetchRequest setFetchBatchSize:20];

   NSPredicate *predicateDate = [NSPredicate predicateWithFormat:@"(date >= %@) AND (date <= %@)", startDate, endDate];

// Edit the sort key as appropriate.

  typeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"type" ascending:YES]; // type refers to an expense or income.

  dateSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:YES];

  if(self.choiceSegmentedControl.selectedIndex == 0)  // UISegment Control for "Sorting Category"
  {
      NSPredicate *predicateCategory = [NSPredicate predicateWithFormat:@"cat == %@", @""];

      NSArray * subPredicates = [NSArray arrayWithObjects:predicateCategory, predicateDate, nil];

      NSPredicate * compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];

      [fetchRequest setPredicate:compoundPredicate];

      choiceSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"cat" ascending:NO];
   }

   NSArray * descriptors = [NSArray arrayWithObjects:typeSortDescriptor, dateSortDescriptor, choiceSortDescriptor, nil];

   [fetchRequest setSortDescriptors:descriptors];
   [fetchRequest setIncludesSubentities:YES];


   if(_fetchedResultsController)
   {
       [_fetchedResultsController release]; _fetchedResultsController = nil;

   }

   // Edit the section name key path and cache name if appropriate.
   // nil for section name key path means "no sections".
  _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:@"type" cacheName:nil];

  _fetchedResultsController.delegate = self;

  NSError *anyError = nil;

  if(![_fetchedResultsController performFetch:&anyError])
  {
      NSLog(@"error fetching:%@", anyError);
  }

  __block double totalAmount = 0;

  [[self.fetchedResultsController fetchedObjects] enumerateObjectsUsingBlock: ^void (Money *money, NSUInteger idx, BOOL *stop) {

    totalAmount += [[money amount] doubleValue];
  }];

  [fetchRequest release];

  //Finally you tell the tableView to reload it's data, it will then ask your NEW FRC for the new data
  [self.dashBoardTblView reloadData];

  self.startDate = startDate;
  self.endDate = endDate;

}

我想使用NSDictionaryResultType但是这给我使用的FRC一个问题(对于节名,填写表视图等)。

我循环通过FRC的代码给出了总金额(收入和支出)但我想要每个类别的总金额(例如:类别“自动”的总数,“娱乐”类别的总数)。请帮助我,我完全被困在这里。

1 个答案:

答案 0 :(得分:0)

我认为你不能按摩你的FRC来返回你需要的那种物体。 NSPredicate只过滤那种对象以返回它不会从数据中创建新对象。

但是,您可以获取按日期过滤的货币对象,然后使用KVC Collection Operators计算货币对象数组中的数据,如下所示:

NSArray *moneyObjectsFilteredbyDate = [self.fetchedResultsController fetchedObjects]
NSArray *categoryStrings = [moneyObjectsFilteredbyDate valueForKeyPath:@"@distinctUnionOfObjects.cat"];
NSArray *sortedCategoryStrings = [categoryStrings sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

NSMutableArray *aggregatedDataObjects = [NSMutableArray array];
for (NSString *aCategoryString in sortedCategoryStrings) {
    NSPredictate *categoryPredicate = [NSPredicate predicateWithFormat:@"cat == %@", aCategoryString];
    NSArray *moneyWithThisCategory  = [moneyObjectsFilteredByDate filteredArrayUsingPredicate:categoryPredicate];
    NSNumber *sum = [moneyWithThisCategory valueForKeyPath:@"@sum.amount"];
    [aggregatedDataObjects addObject:@{@"category" : aCategoryString, @"sum" : sum, @"individualExpenses" : moneyWithThisCategory}];
} 

当然,您可以在配置表格单元格的方法中执行部分操作(如计算总和本身),但我希望它能为您提供一个想法。但我认为您不能以SQL查询或类似形式使用谓词来创建新的数据结构。

您可以执行的其他操作:将类别设置为Core Data模型的单个对象,并在moneyobjects和Category对象之间添加关系。然后你可以获取类别对象。虽然您必须按日期过滤类别的费用。