大家好,我正在开发一个使用 coredata(多线程)的应用程序,下面是使用的 coredata 堆栈(这是通过此处找到的教程设计的:https ://www.cocoanetics.com/2012/07/multi-context-coredata/ )
该模型
- (NSManagedObjectModel *)managedObjectModel {
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"XXX" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
主要背景
- (NSManagedObjectContext *)managedObjectContext{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
_managedObjectContext.parentContext = [self writerManagedObjectContext];
return _managedObjectContext;
}
作家背景
- (NSManagedObjectContext *)writerManagedObjectContext{
if (_writerManagedObjectContext != nil) {
return _writerManagedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_writerManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_writerManagedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _writerManagedObjectContext;
}
持久的存储库
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"XXX.sqlite"];
NSError *error = nil;
NSString *failureReason = @"There was an error creating or loading the application's saved data.";
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:@"XXX" URL:storeURL options:options error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
如您所见,WRITER 上下文是 MAIN 上下文的父级,这意味着 WRITER 将处理将数据保存到存储,同时它还会更新 MAIN 上下文(在内存中)的任何更改。
注意:WRITER 保存到商店,因为 POS 设置为 WRITER 上下文。
在模型中的实体上,我将“Id”设置为数据库中用于 UPSERT 的所有实体(表)的唯一约束(即相当于 SQL insert OR replace
)。
并且 MAIN 和 WRITER 上下文都设置了它们的合并策略,以NSMergeByPropertyObjectTrumpMergePolicy
确保 WRITER、MAIN 和存储之间的对象是同步的。
[[CoreDataCommons mainContext] setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
[[CoreDataCommons writerContext] setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
现在,当我想插入数据库时,我创建了一个新的上下文:
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[context setParentContext:writerManagedObjectContext];
[context performBlock:^{
// Populate entity attributes and save
for (id object in objects){
// Save every 500 objects
if (count % 500 == 0){
if ([context save:&error]){
}
}
count++;
}
// Final save if anything unsaved
if ([context save:&error]){
}
// Save WRITER context which will push changes to MAIN context
[writerManagedObjectContext performBlock:^{
if (![writerManagedObjectContext save:&writerError]) {
DLog(@"Writer: Unresolved error %@, %@", writerError, [writerError localizedDescription]);
}];
}];
问题
当应用程序第一次加载时,它会从 API 加载大约 15000 个对象(JSON 类型),并在大约 3 秒内写入这些数据(我认为这有点太长了,但不是主要问题);但是第一次加载不是问题。ISSUE 来自 API 的后续加载;因此,第二次加载它需要大约 5 分钟来写入相同的数据,并且它还阻塞了主线程。
经过几次调试,我发现当数据库中已有数据时,约束(即UPSERT)导致保存时间过长。这是否意味着它也在做原始的
IF (EXIST){ // UPDATE}ELSE{ // INSERT}
我已经使用了多个上下文来确保不是这种情况,但它似乎仍然持有主线程并且需要花费大量时间来保存。
问题 首先,coredata 堆栈是否会导致任何问题(即死锁、后台进程等)?
其次:这个时间用coredata保存对象正常吗?如果没有,任何人都可以提出优化策略。
第三,我正在考虑绕过 coredata 并直接使用 sqlite。这有什么可预见的障碍吗?除了 coredata 提供的安全层。
欢迎任何想法。
提前致谢。