2017-06-04 8 views
3

私はExpenseCategoryにしか属していない可能性がありますが、Tagを複数持つことができる費用トラッカーを構築しています。 、私はテーブルビューにすべての費用を一覧表示画面でNSFetchedResultsControllerでサブセクションを作成する方法

enter image description here

私は、費用は日付(sectionDate)によってグループ化することにしたい、そしてCategoryによって(または、:これは私のオブジェクトグラフでありますセグメント化されたコントロールを使用して、Tag)。これは意図したUIである:

enter image description here

私はすでに、その後、カテゴリによって、日付別のセクションにそれらを、すべての費用NSFetchedResultsController問い合わせを行うことができますが、私はカテゴリの(1)の合計を取得し、(することはできません2)その中の費用のリスト。どうすればそれを進めることができますか?

let fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult> = { 
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Expense") 
    fetchRequest.resultType = .dictionaryResultType 

    fetchRequest.sortDescriptors = [ 
     NSSortDescriptor(key: #keyPath(Expense.sectionDate), ascending: false) 
    ] 

    fetchRequest.propertiesToFetch = [ 
     #keyPath(Expense.sectionDate), 
     #keyPath(Expense.category) 
    ] 
    fetchRequest.propertiesToGroupBy = [ 
     #keyPath(Expense.sectionDate), 
     #keyPath(Expense.category) 
    ] 

    let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, 
                   managedObjectContext: Global.coreDataStack.viewContext, 
                   sectionNameKeyPath: #keyPath(Expense.sectionDate), 
                   cacheName: nil) 
    return fetchedResultsController 
}() 
+0

は、その日付のグループであるすべてのアイテムについて、同じ 'sectionDate'ですか? –

+0

@JonRoseはい。 'dateSpent'が変更されるたびに' sectionDate'を設定する 'Expense'の拡張があります。 'sectionDate'は、MM/DD/YYコンポーネントのみを持つ' dateSpent'です。 'sectionDate'自体もコアデータに格納されています。一時的なプロパティではありません。 –

答えて

0

私は@ pbasdfの答えに感謝しますが、私はコードを見ていない長い時間の後に私の頭の中に私の頭を包んでいると思います。私がやってに集まってくる代わりにExpenseオブジェクトを取得するのでてきたもの

は、私はサブセクション自身のための新しいエンティティ定義された(CategoryGroupを、私もTagGroupを行います)、代わりにそれらのエンティティをフェッチします。これらのエンティティは、含まれるExpenseオブジェクトへの参照を持ち、グループを表すCategoryまたはTagを参照します。これは私の(部分的に完全な)データモデルである:コードで今はるかに簡単である

enter image description here

そして、私のNSFetchedResultsController

let fetchedResultsController: NSFetchedResultsController<CategoryGroup> = { 
    let fetchRequest = NSFetchRequest<CategoryGroup>(entityName: "CategoryGroup") 
    fetchRequest.sortDescriptors = [ 
     NSSortDescriptor(key: #keyPath(CategoryGroup.sectionDate), ascending: false) 
    ] 
    return NSFetchedResultsController(fetchRequest: fetchRequest, 
             managedObjectContext: Global.coreDataStack.viewContext, 
             sectionNameKeyPath: #keyPath(CategoryGroup.sectionDate), 
             cacheName: "CacheName") 
}() 

欠点は、私が今、絶対にするために、余分なコードを書く必要があるということですExpenseまたはCategoryが作成/更新/削除されるたびにエンティティ間の関係が正しく定義されていることを確認してください。ただし、これはコードで分かりやすいため、私にとっては受け入れられるトレードオフです。

1

Aは、私はこれをやったことがないことをあらかじめ警告する必要がありますが、個人的に次のように私はそれについて設定します::

  1. propertiesToGroupByを使用しないでください:それはあなたを強制的にこれが私の現在のコードです.dictionaryResultTypeを使用してください。つまり、別のフェッチを実行して、基本となる管理対象オブジェクトにしかアクセスできません。
  2. 代わりに、sectionDatecategory.nameを組み合わせて、関連するNSManagedObjectサブクラスに別の計算されたプロパティを追加します。このプロパティはFRCのsectionNameKeyPathとして使用されるため、FRCはsectionDateとカテゴリ名のユニークな組み合わせごとにtableViewにセクションを設定します。
  3. category.nameを、FRCの基礎となるフェッチの別のソート記述子として追加します。これにより、FRCによってフェッチされたExpenseオブジェクトが正しい順序(つまり、同じsectionDateとカテゴリ名を持つすべてのExpenseオブジェクトが一緒になっている)に確実に格納されます。
  4. 各セクションのセクションヘッダービューを追加します。 (FRCの)セクションのnameプロパティには、sectionDateとカテゴリ名の両方が含まれます。ほとんどの場合、categoryDateを取り除いて無視し、カテゴリ名とそれに対応する総数のみを表示することができます(下記参照)。しかし、最初のセクションと、実際には任意のsectionDateの最初のセクションについては、sectionDateのsectionDateと全体の合計を示す追加のビュー(セクションヘッダービュー)を追加します。
  5. 与えられたセクションがsectionDateの最初のセクションであるかどうかは少し微妙です。前のセクションの名前を取得し、sectionDatesを比較することができます。
  6. セクションを折りたたむ/展開するには、各セクションの折りたたまれた/展開された状態を保持する配列を維持します。セクションが折りたたまれている場合は、tableView numberOfRowsInSectionデータソースメソッドで0を返します。拡張されている場合は、FRCによって提供される図を使用します。
  7. カテゴリの合計については、該当するセクションのobjectsアレイを繰り返し処理します(またはこれを達成するには、適切な.reduceを使用してください)。
  8. セクション合計については、該当するsectionDateExpenseオブジェクトのみを含めるようにFRCのフィルタfetchedObjectsをフィルタ処理し、フィルタ処理された配列を繰り返し処理または縮小します。

私が追加または修正する必要がある場合は、訂正が必要です。

関連する問題