2

私はこの問題を1週間にわたって調査していて、解決策がないので、質問をより一般化することを考えました。ユーザーが問題を調べて解決策を提供するのに役立つかもしれません。

シナリオ:

私はiOSアプリケーションを追跡する経費を持っており、「DashBoardViewController」(テーブルビューコントローラー-FRC付き)と呼ばれるビューコントローラーを持っています。これは基本的に、特定の週、月、または年の経費/収入を分類し、セクションヘッダーとして表示しますたとえば、タイトル:(2012年10月1日から10月7日)。特定の週、月、または年に応じて、費用/収入のROWSおよび関連するものが表示されます。

私の質問:

私が達成したいのは:

「Money」エンティティの「Category」属性に基づいて個別の結果を表示し、属性に基づいて「Sum」を計算します。

しかし、「ダッシュボードビューコントローラー」と呼ばれる私のビューコントローラーは、費用または収入になる可能性のある「タイプ」としてのセクション名キーパスを持つNSFetchedResultsControllerで満たされています。個別の結果を取得するために、フェッチリクエストで結果タイプを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 の値は、集計結果の計算 (max や min など) を含め、結果の型 NSDictionaryResultType と組み合わせてサポートされていません。ディクショナリの場合、フェッチから返される配列は永続ストアの現在の状態を反映し、コンテキスト内の保留中の変更、挿入、または削除は考慮されません。

FRC の変更追跡はincludesPendingChanges = YESフェッチ要求を意味しますが、これは では機能しませんNSDictionaryResultType

回避策の 1 つは、変更追跡なしで FRC を使用して、FRC デリゲートを設定しないことです。ただし、テーブル ビューを更新するには、

  • 管理対象オブジェクトのコンテキストを保存し、
  • performFetchFRC とreloadDataテーブル ビューで呼び出します。

別の回避策として、FRC を使用して合計集計なしですべてのセクションと行をフェッチし、結果を使用してメモリ内の集計で新しいテーブル行を計算することができます (例: controllerDidChangeContent)。

更新: (ディスカッションから) もう 1 つの重要な点は、フェッチ リクエストを で使用する場合、フェッチNSDictionaryResultTypesectionNameKeyPathれた結果コントローラの をフェッチ リクエストの に含める必要があることpropertiesToFetchです。

于 2012-11-25T10:59:03.873 に答える