編集:2015 WWDCの「コアデータの新機能」(これは常に最初に視聴するビデオですが、今年は非常に忙しいです)を視聴し、新しいAPIを発表しましたNSBatchDeleteRequest
。これは以前のソリューションよりもはるかに効率的です。
効率的には複数の意味があり、ほとんどの場合、ある種のトレードオフを意味します。ここでは、削除中にメモリを含めたいだけだと思います。
Core Dataには、単一のSOの質問の範囲を超えて、多くのパフォーマンスオプションがあります。
メモリの管理方法は、managedObjectContextとfetchRequestの設定によって異なります。ドキュメントを見て、すべてのオプションを確認してください。ただし、特に、これらのことを覚えておく必要があります。
また、パフォーマンスの側面にも注意してください。このタイプの操作は、別のスレッドで実行する必要があります。
また、オブジェクトグラフの残りの部分も機能することに注意してください(CoreDataが関連オブジェクトの削除を処理する方法のため)。
メモリ消費に関しては、MOCには特に注意すべき2つの特性があります。ここにはたくさんありますが、決して包括的ではありません。実際に何が起こっているかを確認したい場合は、各保存操作の直前と直後にMOCをNSLogします。特に、registeredObjectsとdeletedObjectsをログに記録します。
MOCには、登録済みオブジェクトのリストがあります。デフォルトでは、登録されたオブジェクトは保持されません。ただし、retainsRegisteredObjectsがYESの場合、登録されているすべてのオブジェクトが保持されます。
特に削除の場合、setPropagatesDeletesAtEndOfEventは、関連するオブジェクトの処理方法をMOCに指示します。保存で処理する場合は、その値をNOに設定する必要があります。それ以外の場合は、現在のイベントが完了するまで待機します
非常に大きなオブジェクトセットがある場合は、fetchLimitの使用を検討してください。障害は多くのメモリを消費しませんが、それでもいくらかを消費し、一度に何千も重要ではありません。より多くのフェッチを意味しますが、メモリの量を制限します
また、大きな内部ループがある場合は、独自の自動解放プールを使用する必要があることも考慮してください。
このMOCに親がある場合、保存するとそれらの変更のみが親に移動します。この場合、親MOCがある場合は、それを成長させるだけです。
メモリを制限するために、これを考慮してください(必ずしもあなたのケースに最適ではありません-コアデータオプションがたくさんあります-他の場所で使用しているすべてのオプションに基づいて、あなただけがあなたの状況に最適なものを知っています。
これと非常によく似た、保存がバッキングストアに確実に送られるようにするときに保存に使用するカテゴリをNSManagedObjectContextに作成しました。MOC階層を使用しない場合は必要ありませんが、階層を使用しない理由は実際にはありません(古いiOSにバインドされている場合を除く)。
- (BOOL)cascadeSave:(NSError**)error {
__block BOOL saveResult = YES;
if ([self hasChanges]) {
saveResult = [self save:error];
}
if (saveResult && self.parentContext) {
[self.parentContext performBlockAndWait:^{
saveResult = [self.parentContext cascadeSave:error];
}];
}
return saveResult;
}
コードを少し変更しました...
+ (void)deleteRelatedEntitiesInManagedObjectContext:(NSManagedObjectContext *)context
{
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
[context setUndoManager:nil];
[fetch setEntity:[NSEntityDescription entityForName:NSStringFromClass(self) inManagedObjectContext:context]];
[fetch setIncludesPropertyValues:NO];
[fetch setFetchLimit:500];
NSError *error = nil;
NSArray *entities = [context executeFetchRequest:fetch error:&error];
while ([entities count] > 0) {
@autoreleasepool {
for (NSManagedObject *item in entities) {
[context deleteObject:item];
}
if (![context cascadeSave:&error]) {
// Handle error appropriately
}
}
entities = [context executeFetchRequest:fetch error:&error];
}
}