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. Надеюсь, поможет!

Другие вопросы по тегам