3

2 つのコア データ エンティティがあるとします。Student エンティティと Class エンティティ。この例では、学生は正確に 1 つのクラスに所属しており、クラスには多くの学生がいる可能性があります。

これらが大きなクラスであるとしましょう。つまり、各クラスには 1000 人の生徒がいます。

Class エンティティは次のようになります。

NSString* name
NSArray* students

および Student エンティティ:

NSString* name
Class* class
NSString* grade

私の UI では、クラスを表示したいと考えています。特定の成績を持つ学生のを表示したい。つまり、1000 人の生徒のクラスの場合、50 人が A、500 人が B、200 人が C というようになります。

これらのカウントを Core Data から取得する最も効率的な方法は何ですか?

私は現在、NSFetchedResultsController を使用して、group by + count クエリのフェッチ要求を渡しています。私は NSFetchedResultsController を使用しているため、特定の成績を持つ学生の数が変化すると UI が更新されます。ただし、かなり遅いです。

クエリを実行せずにこの情報を取得する方法はありますか? つまり、生徒がクラスに追加されるか、成績が変更されると、クラスのプロパティがすべての成績カウントで更新されます。そのため、カウントが必要な場合、それらは単なるクラスのプロパティであり、クエリは必要ありません。

出来ますか?

4

3 に答える 3

9

この取得リクエストを試すことができます:

NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Student"];
[request setResultType:NSDictionaryResultType];
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"grade"];
NSExpression *countExpression = [NSExpression expressionForFunction:@"count:" arguments:[NSArray arrayWithObject:keyPathExpression]];

NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:@"gradeTypeCount"];
[expressionDescription setExpression:countExpression];
[expressionDescription setExpressionResultType:NSInteger64AttributeType];
[request setPropertiesToFetch:@[@"grade",expressionDescription]];
[request setPropertiesToGroupBy:@[@"grade"]];
[request setPredicate:[NSPredicate predicateWithFormat:@"theClass == %@",cls.objectID]];

これにより、目的の値を保持する辞書の配列が生成されます。
ここでの問題は、FRC がこれらの結果の変更を追跡できないことです。したがって、そもそも FRC を使用する理由はありません。
それでも、これは非常に軽量な要求であり、一定の時間間隔で発行して UI を更新することができます。

(たとえば 2 秒で、管理対象オブジェクトを処理しなくなったので、プロセス全体をバックグラウンドで実行し、必要に応じて結果をメイン スレッドにダンプできます)

または、メイン コンテキストの変更をリッスンし、学生要素が変更された場合は、カウントを再度取得します。

これにより、すべての要素をまとめてフェッチすることが回避Studentされます (記述されたコストで)。

于 2013-04-08T08:36:50.663 に答える
0

迅速な非常に簡単な方法。

let request = NSFetchRequest(entityName: "BWCoreDataNotification")
request.predicate = NSPredicate(format: "type = 'purchase_reward'")

var error: NSError?
let numberOfNotifications = NSManagedObjectContext.MR_defaultContext().countForFetchRequest(request, error: &error)
于 2016-05-02T08:54:04.483 に答える