同时在 CoreData 中工作

Posted

技术标签:

【中文标题】同时在 CoreData 中工作【英文标题】:Working in CoreData simultaneously 【发布时间】:2013-03-12 14:03:34 【问题描述】:

首先,对不起,如果我的英语不完美,我不是以英语为母语的人;)!

我正在开发一个应用程序,它从 iCal 检索 EKEvent 并将它们添加到我的应用程序中。

应用程序的目的是一个日历,所以:

用户从他想要的日历中检索 iCal 的 EKEvent。

EKEvent 被保存到一个名为“Event”的实体中。

用户可以在应用程序中编辑、添加、删除事件 - EKEvent 关联也将在 iCal 中进行修改。

问题:当用户在 iCal 中修改某些内容时,必须将其修改到我的应用程序中,因此我发现的唯一方法是从 iCal 检索所有 EKEvent - 当应用程序变为活动时 - 并将其复制到名为“事件备份”。当 iCal 中的所有 EKEvent 都被很好地检索并保存到“EventBackup”实体中时,我将该实体复制到我的主实体“Event”中。

我正在与

异步成功地做到这一点
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void)  );

但我必须继续使用我的应用程序 - 因此从 CoreData 检索 Event * - 而我正在执行 EventBackup...如果我正在处理 CoreData,我的应用程序会崩溃。

你能帮忙吗,或者给我一些不同于我正在做的事情的建议。

非常感谢您帮助我!

【问题讨论】:

【参考方案1】:

你应该看看 NSManagedObjectContext 的 performBlock: 方法。具体来说,您应该创建一个子上下文,在后台线程中对其进行更改,然后侦听保存通知以将其合并到父上下文中。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(managedObjectContextDidSave:) name:NSManagedObjectContextDidSaveNotification object:nil];

NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[childContext setParentContext:self.managedObjectContext];
[childContext performBlock:^

    //Do everything here...

    NSError *error = nil;
    [context save:&error];
    if (error) 
        NSLog(@"Error saving child context:%@", error.localizedDescription);
    

 ];

监听要保存的子上下文,然后保存主上下文。

 - (void)managedObjectContextDidSave:(NSNotification *)notification
 
    if ([notification object] != self.managedObjectContext) 
       dispatch_sync(dispatch_get_main_queue(), ^
         [self.managedObjectContext save:nil];
      );
    
  

【讨论】:

首先,感谢您的回答,我正在尝试。你的意思是我应该对“childContext”进行所有更改,然后当我的块完成时它会通知:“managedObjectContextDidSave”但我没有看到我何时将我的 childContext 复制到我的 parentContext 中?没有对象发送到 managedObjectContextDidSave 我收到一个错误:*** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“父 NSManagedObjectContext 必须使用 NSPrivateQueueConcurrencyType 或 NSMainQueueConcurrencyType。”【参考方案2】:

为了更清楚地了解我在做什么 - 使用您的代码。

块中的方法正在处理childContext的NSManagedObjectContext

我在 AppDelegate 中,那个

- (void)methodToBeCalledEveryTimeTheAppBecomeActive


    NSManagedObjectContext *contextParent = [[LavigneCoreData defaultManager] managedObjectContext];


    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(managedObjectContextDidSave:) name:NSManagedObjectContextDidSaveNotification object:nil];

    childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [childContext setParentContext:contextParent];
    [childContext performBlock:^

        [self copySpecialsEvents];
        [self clearBackUpEntity];
        [self getCalendarWhichHasBeenSelected];
        [self copyNotesIntoBackUpEntity];
        [self clearEntityEvent];
        [self deepCopyFromBackUpEntityToEntity];

        NSError *error = nil;
        [contextParent save:&error];
        if (error) 
            NSLog(@"Error saving child context:%@", error.localizedDescription);
        
    ];

我在线收到错误消息:[childContext setParentContext:contextParent];

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Parent NSManagedObjectContext must use either NSPrivateQueueConcurrencyType or NSMainQueueConcurrencyType.'

编辑:

我通过更改修复了这个错误

_managedObjectContext = [[NSManagedObjectContext alloc] init];

_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

【讨论】:

以上是关于同时在 CoreData 中工作的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 中工作 NSPersistentCloudKitContainer 时获取错误堆栈跟踪

CoreData 在插入和删除时崩溃同时发生

SwiftUI Picker 多个错误,核心数据,布局

Core Data 轻量级迁移 - 现有实体是不是添加了新属性?

在现有 CoreData 中添加属性,同时使用默认方法,即 persistentContainer

在 iOS 的 CoreData 中同时插入