同时在 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 时获取错误堆栈跟踪
Core Data 轻量级迁移 - 现有实体是不是添加了新属性?