iOS: обновление базы данных базы данных требует много времени
В моем проекте я должен загрузить файл JSON, созданный следующим образом:
[{"id":"2","n":"One"},{"id":"2","n":"Two"},{"id":"2","n":"Three"},...]
мой код такой:
- (void) startPopulate:(NSArray *)array{
NSManagedObjectContext *context = [[self sharedAppDelegate] managedObjectContext];
NSFetchRequest *fetchRequest=[NSFetchRequest fetchRequestWithEntityName:@"Myentity"];
NSError *error = nil;
for (id element in array){
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"id == %@",[element objectForKey:@"id"]]];
Myentity *myE = [[context executeFetchRequest:fetchRequest error:&error] lastObject];
//update
if (myE != nil){
myE.id_e = [element objectForKey:@"id"];
myE.name = [element objectForKey:@"n"];
}
//new element
else{
Myentity *myE = [NSEntityDescription insertNewObjectForEntityForName:@"Myentity" inManagedObjectContext:context];
myE.name = [element objectForKey:@"n"];
myE.id_e = [element objectForKey:@"id"];
}
}
if (![context save:&error]) {
NSLog(@"couldn't save: %@", [error localizedDescription]);
}
else{
NSLog(@"DB UPDATED");
}
}
Как видите, я передаю в методе массив словарей и проверяю, существует сущность или нет. Работает нормально и у меня нет особых проблем. "Проблема", если можно так назвать, состоит в том, что у меня есть 12000 элементов, и этот метод выполняется около 53 секунд. Это очень очень медленно. Какой тип решения я могу принять, чтобы сделать его более быстрым? Или я должен просто поместить этот метод в фоновый процесс? Спасибо
2 ответа
Вы должны поместить это в фоновый процесс?
Абсолютно. Запустите фоновый поток и создайте дочерний контекст из основного контекста, чтобы выполнить всю работу.
Что еще можно сделать
Каждое несохраненное изменение, которое вы вносите в контекст управляемого объекта, сохраняется в памяти. Внесение тысяч изменений перед сохранением нецелесообразно, так как это займет много памяти, но и сохранение займет много времени.
Вы можете объединить обновления в, скажем, 100 изменений за раз и сохранить каждый блок из 100.
альтернативы
Если вы всегда загружаете эти элементы для приложения, вы также можете предварительно загрузить их в БД и связать их с самим приложением.
Таким образом, вам не нужно сохранять их во время выполнения, так как они уже там.
Вот как вы создаете фоновый поток при использовании основных данных:
dispatch_queue_t fetchQ = dispatch_queue_create("JSON Fetcher", NULL);
dispatch_async(fetchQ, ^{
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
context.parentContext = self.mainMOC;
[context performBlock:^{
// implement your own background code here
NSError *error;
if(![context save:&error]) {
// handle error
}
}];
});
Вам также необходимо сохранить результаты, чтобы они были переданы в mainMOC. Надеюсь, поможет!