iOS:更新核心数据db需要大量时间

时间:2014-04-01 08:46:48

标签: ios core-data nsfetchrequest nsentitydescription

在我的项目中,我应该下载以这种方式制作的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 个答案:

答案 0 :(得分:0)

你应该把它放在后台进程吗?

绝对。启动后台线程并从主上下文创建子上下文以完成所有工作。

还能做些什么

您对托管对象上下文所做的每个未保存的更改都存储在内存中。在保存之前进行数千次更改是不可取的,因为它会占用大量内存,但节省时间也需要很长时间。

您可以批量更新,一次更改100个,并保存每个块100个。

<强>替代

如果您总是为应用程序加载这些项目,那么您也可以将它们预加载到数据库中并将其捆绑到应用程序本身。

这样你就不需要在运行时保存它们,因为它们已经在那里。

答案 1 :(得分:0)

以下是使用核心数据时创建后台线程的方法:

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。希望它有所帮助!