これは既知のバグ(新しいオブジェクトが保存されたときにネストされたコンテキストが永続的なIDを取得しない)である可能性があり、今後のリリースで修正される予定です...
ただし、永続的なIDを要求できるはずですが、挿入されたオブジェクトでのみ要求する必要があります。
[moc obtainPermanentIDsForObjects:moc.insertedObjects.allObjects error:0];
ただし、永続IDを取得せずに保存すると、一時IDが親コンテキストに伝播されるため、MOCを保存する前にこれを行う必要があります。たとえば、mainMocに保存してからIDSを取得する場合、backgroundMOCにはまだ一時IDが残っているため、今後保存すると重複データが作成されます。
永続IDの取得はデータベースにまで及ぶことに注意してください。ただし、メインMOCの子MOCで取得する場合は、これが発生している間はメインスレッドをまったくブロックしないでください。
したがって、最低レベルのMOCからの保存では、このようなものを効果的に使用する必要があります(もちろん、適切なエラー処理を使用します)...
[backgroundMoc performBlock:^{
[backgroundMoc obtainPermanentIDsForObjects:backgroundMoc.insertedObjects.allObjects error:0];
[backgroundMoc save:0];
[mainMoc performBlock:^{
[mainMoc save:0];
[masterMoc performBlock:^{
[masterMoc save:0];
}];
}];
}];
必要に応じて、他にもプレイできるゲームがいくつかあります。
これに似たNSManagedObjectのカテゴリを提供します...
@implementation NSManagedObject (initWithPermanentID)
- (id)initWithEntity:(NSEntityDescription *)entity insertWithPermanentIDIntoManagedObjectContext:(NSManagedObjectContext *)context {
if (self = [self initWithEntity:entity insertIntoManagedObjectContext:context]) {
NSError *error = nil;
if (![context obtainPermanentIDsForObjects:@[self] error:&error]) {
@throw [NSException exceptionWithName:@"CoreData Error" reason:error.localizedDescription userInfo:error.userInfo];
}
}
return self;
}
+ (NSArray*)createMultipleObjects:(NSUInteger)count withEntity:(NSEntityDescription *)entity inManagedObjectContext:(NSManagedObjectContext *)context {
NSMutableArray *array = [NSMutableArray arrayWithCapacity:count];
for (NSUInteger i = 0; i < count; ++i) {
[array addObject:[[self alloc] initWithEntity:entity insertIntoManagedObjectContext:context]];
}
NSError *error = nil;
if (![context obtainPermanentIDsForObjects:array error:&error]) {
@throw [NSException exceptionWithName:@"CoreData Error" reason:error.localizedDescription userInfo:error.userInfo];
}
return array;
}
@end
さて、最初のものでは、データベースにアクセスして、作成された各エンティティのIDを作成するためにお金を払っていますが、それほど多くはなく、バックグラウンドスレッドで発生しており、各ディップは短いです...
まあ、それは最高ではありませんが、それは便利です。さらに、2つ目は同じオブジェクトを複数作成し、それらの永続IDを同時に取得します。
PSCに直接接続されたMOCを使用して、DidChangeイベントを監視することもできますが、これは以前の方法と同じです。
残念ながら、別のMOCでpersistentID要求を作成してObjectIDを渡すことはできませんが、別のMOCでDBにプロトタイプオブジェクトを作成し、それらのObjectIDを提供することはできます。
プロトタイプファクトリはかなり一般的なパターンであり、そのルートをたどると、最終的なバグ修正がここに到達したときに小さな変更を加えるのは非常に簡単です。
編集
スヴェンに応えて...
新しい複雑なグラフを作成する場合は、作成直後に永続的なIDを取得する必要があります。ストアへのヒット数を減らすには、それらをすべて作成し、一度にIDを取得してから、それらを接続し始める必要があります。
正直なところ、これはすべて、現在存在するバグを回避することです。これらのバグは、中小規模の更新で回避する価値があります。バグが修正されたとき、コードは同じになります(取得はありません)。したがって、小規模なインポートにはこの方法をお勧めします。
大規模な更新を行う場合は、「古い」方法を使用することをお勧めします。PSCに直接接続された新しいMOCを作成します。そこですべての変更を行い、「ライブ」コンテキストをそれらのDidSave通知からマージするだけです。
最後に、永続IDのデータベースへの影響について。MOCを破棄してもかまいません。ディスクがヒットし、メタデータが変更されますが、オブジェクトは保持されません。
正直なところ、結果として空きスペースがあるかどうかを確認するための大規模なテストは行いませんでした。そのため、それを実行して、私と一緒に戻ってください。
ディスク上の実際のデータベースファイルサイズを確認してから、10000個のオブジェクトを作成し、永続IDを取得して、MOCを解放し、サイズをもう一度確認します。
影響がある場合は、オブジェクトを削除してみるか、大規模な更新後にデータベースでバキュームを実行して、それが機能するかどうかを確認できます。
捨てるだけのオブジェクトをたくさん作成する場合は、データベースにアクセスする必要はありません。PSCに直接接続して、古い忠実な通知を使用することをお勧めします。