Как ускорить вставку нового объекта в сущность с Core Data - PullRequest
2 голосов
/ 07 сентября 2011

Вот мой код, который берет некоторые данные JSON и вставляет их в сущность комнаты основных данных:

for (NSDictionary *room in rooms)
    {
        NSDictionary *thisroom = [room objectForKey:@"room"];
        NSString *roomidstring = [thisroom objectForKey:@"roomid"];
        int roomid = [roomidstring intValue];
        NSString *roomname = [thisroom objectForKey:@"roomname"];
        NSString *buildingidstring = [thisroom objectForKey:@"buildingid"];
        int buildingid = [buildingidstring intValue];

        // import into database
        NSManagedObject *roomInfo = [NSEntityDescription insertNewObjectForEntityForName:@"room" inManagedObjectContext:context];
        [roomInfo setValue:[NSNumber numberWithInteger:roomid] forKey:@"roomid"];
        [roomInfo setValue:roomname forKey:@"roomname"];
        [roomInfo setValue:[NSNumber numberWithInteger:buildingid] forKey:@"buildingid"];
         if (![context save:&error]) {
            NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
        }
    }

Это невероятно медленно при вставке около 900 объектов.Есть ли способ сделать это более эффективным и / или ускорить его?

Спасибо!

Ответы [ 4 ]

8 голосов
/ 07 сентября 2011

Да, НЕ сохраняйте, пока не закончите цикл, или сохраняйте в пакетном режиме, если проблема с памятью.Операция сохранения очень дорогая, поэтому вам следует избегать сохранения часто в таких узких циклах, как этот.

for (NSDictionary *room in rooms)
{
    NSDictionary *thisroom = [room objectForKey:@"room"];
    NSString *roomidstring = [thisroom objectForKey:@"roomid"];
    int roomid = [roomidstring intValue];
    NSString *roomname = [thisroom objectForKey:@"roomname"];
    NSString *buildingidstring = [thisroom objectForKey:@"buildingid"];
    int buildingid = [buildingidstring intValue];

    // import into database
    NSManagedObject *roomInfo = [NSEntityDescription insertNewObjectForEntityForName:@"room" inManagedObjectContext:context];
    [roomInfo setValue:[NSNumber numberWithInteger:roomid] forKey:@"roomid"];
    [roomInfo setValue:roomname forKey:@"roomname"];
    [roomInfo setValue:[NSNumber numberWithInteger:buildingid] forKey:@"buildingid"];
}


if (![context save:&error]) {
     NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
}
1 голос
/ 07 сентября 2011

Как насчет перемещения вызова [context save] из цикла и сохранения всех их за одну операцию? Кажется, что сохранение каждый раз делает вещи намного медленнее.

0 голосов
/ 12 мая 2016

Дополнительно (к ответу Джо) вы также можете ускорить время сохранения, выполнив сохранение в другом потоке (NSPrivateQueueConcurrencyType):

- (void)openDataBase {
    // Set up _persistentStoreCoordinator accordingly.

    privateWriterContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [privateWriterContext setPersistentStoreCoordinator:_persistentStoreCoordinator];

    context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    context.parentContext = _privateWriterContext;
}

- (void)save
{
    [context performBlock:^{
        NSError *error;
        if (![context save:&error]) { // This will forward save to the parent, which is privateWriterContext.
            NSLog(@"Error saving main DB: %@, %@", error, [error userInfo]);
            NSAssert(false, nil);
        }
        [privateWriterContext performBlock:^{
            NSError *error;
            if (![privateWriterContext save:&error]) {
                NSLog(@"Error saving writer DB: %@, %@", error, [error userInfo]);
                NSAssert(false, nil);
            }
        }];
    }];
}
0 голосов
/ 07 сентября 2011

Импорт один раз, копирование файла хранилища в каталог документов, обновление кода координатора постоянного хранилища для загрузки указанного файла из нового места.

...