开发者

How to speed up inserting new object into entity with Core Data

Here's my code, which is taking some JSON data and inserting it into the Core Data room entity:

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:[NSN开发者_开发技巧umber 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]);
        }
    }

It is incredibly slow when inserting around 900 objects. Is there any way to make this more efficient and/or to speed it up?

Thanks!


Yes there is, DO NOT save until you finish the loop, or save in batches if memory is an issue. The save operation is very expensive so you should avoid saving often in tight loops like this one.

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]);
}


How about moving the [context save] call out of the loop and saving all of them in one operation? It seems like doing a save every time would make things much slower.


Import once, copy storage file to documents directory, update persistent store coordinator code to load the said file from new location.


Additionally (to Joe's answer), you also can speed up the save time by doing save on another thread (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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜