1

大家好,我正在开发一个使用 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 提供的安全层。

欢迎任何想法。

提前致谢。

4

0 回答 0