Удаление / удаление записей в Core Data очень очень медленно
Я делаю последние штрихи в приложении и испытываю трудности с массовым удалением записей. При нажатии кнопки набор прибл. 3500 записей должны быть добавлены в базу данных. Это не проблема, и занимает ок. 3-4 секунды.
Но иногда (не часто, но опция должна быть там) все эти записи должны быть удалены. Я только что запустил эту операцию, и это заняло 20 минут. Что здесь может быть не так? Существует только одна зависимость, все записи являются дочерними для определенной коллекции.
Я добавляю все элементы в набор, удаляю их из Коллекции и затем удаляю один за другим. Каждые 5% я обновляю диалог, и когда все сделано, я фиксирую изменения. Но удаление элементов просто занимает много времени (как я вижу, прогресс прогресс очень медленно)
- (void) deleteList:(DOCollection *) collection {
// For the progress dialogue
NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObject:@"Clearing vocabulary list!" forKey:@"message"];
float totalItems = [collection.items count];
float progress = 0;
float nextProgressRefresh = 0.05;
NSMutableSet* itemsSet = [NSMutableSet set];
for (DOItem* item in collection.items) {
[itemsSet addObject:(NSNumber*)[NSNumber numberWithInt:[item.itemId intValue]]];
}
// Remove all of them from the collection
[managedObjectContext performBlockAndWait:^{
[collection setItems:[NSSet set]];
}];
for (NSNumber* itemId in itemsSet) {
DOItem* item = [itemController findItem:[itemId intValue]];
if (item != nil) {
[[self itemController] removeItem:item];
}
progress++;
if((nextProgressRefresh < (progress / totalItems))){
NSString* sProgress = [NSString stringWithFormat:@"%f", (progress / totalItems) * 0.85];
//[dict setValue:@"Saving the database...!" forKey:@"message"];
[dict setValue:sProgress forKey:@"progress"];
[[NSNotificationCenter defaultCenter] postNotificationName:kUpdatePleaseWaitDialogue object:dict];
nextProgressRefresh = nextProgressRefresh + 0.05;
}
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[managedObjectContext performBlockAndWait:^{
[[self collectionController] commitChanges];
}];
[[NSNotificationCenter defaultCenter] postNotificationName:kSavingDataComplete object:nil];
});
//NSLog(@"Wait 2!");
[NSThread sleepForTimeInterval:1];
}
в DOItemController:
- (void) removeItem: (NSManagedObject*) item {
[[self managedObjectContext] deleteObject:item];
}
1 ответ
Не уверен, как вы спроектировали свои модели данных. Но я бы настроил его на каскадное удаление ваших объектов. Если объекты DOItem уникальны для коллекции DOCollection, вы можете установить правило удаления каскадным. Это автоматически удалит связанный DOItem, а также удалит его из объекта набора элементов DOCollection.
Чтобы удалить объекты DOItem из коллекции DOCollection, проверьте файл DOCollection.h, у вас должен быть метод, аналогичный
-(void)removeDOItemObjects:(NSSet *)value
в противном случае они могут по-прежнему динамически генерироваться Core Data для вас. В вашем заголовочном файле у вас должно быть что-то вроде:
@property(nonatomic,retain) DOItem *items
тогда в вашем файле реализации у вас должно быть что-то вроде:
@synthesize items
Соответствующие методы, которые должны быть сгенерированы для них автоматически:
-(void)addItemsObject:(DOItem*)value
-(void)addItems:(NSSet *)values
-(void)removeItemsObject:(DOItem *)value
-(void)removeItems:(DOItem *)values
-(NSSet *)items
См. "Пользовательские методы доступа к многим отношениям" здесь для получения дополнительной информации.
Этот метод предназначен для вас, когда вы создаете модель данных и связанные файлы реализации и должен быть сильно оптимизирован Core Data. Тогда все, что вам нужно сделать, чтобы удалить объекты, это что-то вроде:
- (void) deleteList:(DOCollection *) collection {
// Remove all of them from the collection
[managedObjectContext performBlockAndWait:^{
// Updated 01/10/2012
[collection removeItems:collection.items];
NSError *error = nil;
if (![managedObjectContext save:&error]) {
NSLog(@"Core Data: Error saving context."); }
};
}];
}
Возможно, вы захотите проверить эффективность удаления с помощью этого метода и продолжить предоставлять пользователю обратную связь. Если производительность является проблемой, рассмотрите шаг, где вы разделяете настройку на куски и выполняете описанный выше метод для каждого шага, обновляете пользовательский интерфейс и т. Д.
Опять же, я не уверен насчет архитектуры вашего приложения, но на первый взгляд это выглядит как проблема.
Удачи!