2

一周以来我一直在研究这个问题,但没有得到任何解决方案,所以我想把这个问题更概括,可能会帮助用户研究它并给我一个解决方案。

设想:

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

我的问题:

我想要完成的是:

根据“Money”实体的“Category”属性显示不同的结果,并根据该属性计算“Sum”。

但是,我的名为“仪表板视图控制器”的视图控制器充满了 NSFetchedResultsController,其部分名称键路径为“类型”,可以是费用或收入。为了获得不同的结果,我将在我的 fetch 请求中使用 Result 类型作为 NSDictionaryResultsType ,这将给我唯一的结果,但 FRC 失败,它不适用。那么,我将如何获得我的部分名称呢?我已经发布了下面的代码。

编辑 - 基于马丁的建议

   - (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];
    [fetchRequest setPredicate:predicateDate];


    // Edit the sort key as appropriate.

    typeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"type" ascending:YES];

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

    if(self.choiceSegmentedControl.selectedIndex == 0)
    {
        choiceSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"cat" ascending:NO];
    }

    if(self.choiceSegmentedControl.selectedIndex == 1)
    {
        choiceSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"vendor" ascending:NO];
    }

    if(self.choiceSegmentedControl.selectedIndex == 2)
    {        
        choiceSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"paidBy" ascending:NO];
    }

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

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

    NSError * anyError = nil;

    NSArray *propertiesToFetch = [[NSArray alloc] initWithObjects:
                                  [entity.propertiesByName objectForKey:@"cat"],
                                  nil];

    [fetchRequest setReturnsDistinctResults:YES];
    [fetchRequest setResultType:NSDictionaryResultType];
    [fetchRequest setPropertiesToFetch:propertiesToFetch];

    NSArray * objects = [context executeFetchRequest:fetchRequest error:&anyError];

    for (NSDictionary *d in objects)
    {
        NSLog(@"NSDictionary = %@", d);
    }

    NSSet *uniqueSet = [NSSet setWithArray:[objects valueForKey:@"cat"]];

    uniqueArray = [NSMutableArray arrayWithArray:[uniqueSet allObjects]];

    self.categoryArray = uniqueArray;

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

    }

    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:@"type" cacheName:nil];

    //self.fetchedResultsController.delegate = self; in order to stop "change tracking"

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

    [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;


}

使用此代码,SECTION NAME KEY PATH 不起作用,它抱怨该对象将被放置在未命名的部分中。

4

1 回答 1

2

获取的结果控制器不支持更改跟踪(即设置 FRC 委托)与NSDictionaryResultType.

原因记录在setIncludesPendingChanges:函数中:

特别注意事项

不支持 YES 值与结果类型 NSDictionaryResultType 一起使用,包括聚合结果的计算(例如 max 和 min)。对于字典,从 fetch 返回的数组反映了持久存储中的当前状态,并且不考虑上下文中的任何未决更改、插入或删除。

FRC 的更改跟踪意味着includesPendingChanges = YES获取请求,这不适用于NSDictionaryResultType.

一种解决方法可能是使用没有更改跟踪的 FRC ,因此您不要设置 FRC 委托。但这意味着要更新表格视图,您必须

  • 保存托管对象上下文,以及
  • 调用performFetchFRC 和reloadData表视图。

另一种解决方法可能是使用 FRC 来获取所有没有 sum 聚合的部分和行,并使用结果来计算具有内存中聚合的新表行(例如 in controllerDidChangeContent)。

更新:(来自讨论)另一个重要的一点是,如果您使用 fetch 请求NSDictionaryResultType,那么sectionNameKeyPathfetched results 控制器的 必须包含在propertiesToFetchfetch 请求中。

于 2012-11-25T10:59:03.873 回答