【问题标题】:Show distinct results in fetch request, group by an attribute and calculate the total for that attribute在获取请求中显示不同的结果,按属性分组并计算该属性的总数
【发布时间】:2012-11-05 19:38:51
【问题描述】:

场景:

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

我的问题:

我想要完成的是:

假设我在三个不同的日期(分别为 2012 年 11 月 11 日、11 月 14 日、11 月 16 日)保存了 3 项新的费用,类别名称为“汽车”。

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

我编写了一些代码位,它给了我相同类别的三行而不是我真正想要的(同一类别的一行),我不知道如何计算它们的总数?应该与此处的 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 中循环的代码为我提供了总金额(收入和支出),但我想要每个类别的总金额(例如:类别“汽车”的总金额,“娱乐”类别的总金额)。请帮帮我,我完全被困在这里了。

【问题讨论】:

  • @Marcus S. Zarra 你能帮忙吗?

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


【解决方案1】:

我不认为你可以按摩你的 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 查询或类似形式的谓词来创建新的数据结构。

您可以做的其他事情:使类别成为您的核心数据模型的单个对象,并在moneyobjects 和类别对象之间添加关系。然后你可以只获取类别对象。尽管您随后必须按日期过滤某个类别的费用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    • 2017-05-18
    • 2017-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多