0

2 つの別個のコア データ ストアを使用するアプリケーションがあります。1 つはユーザー データ用、もう 1 つは読み取り専用コンテンツ データ用です。それらの間に関係を作成するために、関係を使用することはもちろん禁止されているため、コンテンツ ストアへの参照は ID によって管理されます。

これはほとんどの場合うまくいきますが、特定のフェッチでは難しいことがわかります。

次の例を見てみましょう: 数百の映画 (それぞれのレコードが読み取り専用ストアに格納されている) を持つアプリケーションがあり、ユーザーが映画を見るたびに、書き込み可能なユーザー ストアにレコードが作成されるとします。Movie と呼ばれる 1 つのエンティティと MovieHistory と呼ばれる別のエンティティを持つようにモデルを設定する場合があります。

動画には、識別子 (NSNumber) と呼ばれる属性があります。

MovieHistory には、movieIdentifier という属性 (Movie へのクロスストア参照)、viewDate 属性 (NSDate)、およびフェッチされたプロパティ「movie」があり、宛先は Movie に設定され、述語は (SELF.identifier == $FETCH_SOURCE. movieIdentifier)。

最近見た 10 本の映画を重複なしで取得したいとします (以前に見た映画を見ると、リストの一番上にジャンプするはずです)。次のコードを使用できるようにしたいと思います。

NSError *error = nil;

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName: @"MovieHistory"];

NSSortDescriptor *dateDescriptor = [[NSSortDescriptor alloc] initWithKey:@"viewDate" ascending:NO];

NSEntityDescription* entity = [NSEntityDescription entityForName:@"MovieHistory" inManagedObjectContext: moc];
NSAttributeDescription* movieIdentifierDesc = [entity.attributesByName objectForKey:@"movieIdentifier"];
NSFetchedPropertyDescription *movieDesc = [entity.propertiesByName objectForKey:@"movie"];

[request setFetchLimit: limit];
[request setSortDescriptors: [NSArray arrayWithObject: dateDescriptor]];
[request setPropertiesToFetch:[NSArray arrayWithObjects: movieIdentifierDesc, movieDesc, nil]];
[request setPropertiesToGroupBy:[NSArray arrayWithObject: movieIdentifierDesc]];
[request setResultType:NSDictionaryResultType];

NSArray *results = [moc executeFetchRequest: request error: &error];

if(error != nil)
    NSLog(@"Error fetching last viewed movies: %@", error);

return results;

このコードは、フェッチされたプロパティ (「MovieHistory」内の「movie」) がこの場合に使用する無効なプロパティであることを示す例外をスローします。NSDictionaryResultType を使用する場合、フェッチされたプロパティは使用できません。ただし、戻り値の型が NSDictionaryResultType でない場合は、setPropertiesToGroupBy: も使用できません。日付で並べ替え、重複した映画を削除するには、グループ化が必要です。

setPropertiesToFetch: に送信された配列から取得したプロパティを削除すると、正常に動作します。しかしもちろん、ループ内で各 MovieRecord を 1 つずつ引き出す必要があります。

私がやろうとしていることを達成するための最良の方法は何ですか? ID をフェッチして結果を 1 つずつループする必要なく、これを行う方法はありますか?

ありがとう、

4

1 に答える 1

0

しかし、私はあなたの投稿全体を正確にフォローしていませんでした...

2 つの個別のフェッチ操作を発行できます。1 つ目は、そのデータベースから MovieHistory オブジェクトを取得します。

すべての映画識別子をコレクションに入れてから、IN キーワードを使用して映画データベースにフェッチします。

NSPredicate *moviePredicate = [NSPredicate predicateWithFormat: @"identifier IN %@", allMovieIdentifiers];

他のソリューションほどエレガントではありませんが、書きやすく、さらに重要なことに、読みやすく、理解しやすく、変更しやすいです。プログラマーは最初に最適化することを忘れないでください。

于 2012-07-12T17:44:15.310 に答える