我在后台 GCD 线程中使用核心数据时遇到问题...我想更新一条记录,但在获取它并设置值后,它似乎并没有真正保存更新的记录。
isUpdate
是我设置的 BOOL,它告诉我我是否正在运行第一次解析/保存,或者它是否是我需要更新的记录。就我而言,当我更新记录时,它实际上似乎并没有在我的商店中更新。
我正在使用MagicalRecord助手。这是我的代码:
// Create background context
NSManagedObjectContext *backgroundContext = [[NSManagedObjectContext alloc] init];
[backgroundContext setPersistentStoreCoordinator:[NSPersistentStoreCoordinator defaultStoreCoordinator]];
// Save the background context and handle the save notification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(backgroundContextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:backgroundContext];
// Parsing data...
//..
Record *record;
if (!isUpdate) {
record = [NSEntityDescription insertNewObjectForEntityForName:@"Record" inManagedObjectContext:backgroundContext];
} else {
NSPredicate *recordPredicate = [NSPredicate predicateWithFormat:@"SELF.tag == %@", [[node attributeForName:@"tag"] stringValue]];
record = [Record findFirstWithPredicate:recordPredicate];
}
[record setTitle:[[recordNode attributeForName:@"title"] stringValue]];
// Parsing other data...
//..
NSError *error = nil;
// save the context
[backgroundContext save:&error];
if (error) {
NSLog(@"An error occurred: %@", error);
}
这是通知:
- (void)backgroundContextDidSave:(NSNotification *)notification {
// Make sure we're on the main thread when updating the main context
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(backgroundContextDidSave:)
withObject:notification
waitUntilDone:NO];
return;
}
// merge in the changes to the main context on the main thread
[[NSManagedObjectContext defaultContext] mergeChangesFromContextDidSaveNotification:notification];
}
你的代码对我来说听起来很奇怪。
为什么要在后台线程中注册NSManagedObjectContextDidSaveNotification
通知?也许我错了,但您需要在应用程序的不同点注册该通知。
如果你想让它工作,你可以在主线程中注册该通知。例如,您可以在 AppDelegate
.
例如didFinishLaunchingWithOptions:
方法中,您可以执行
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(backgroundContextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:backgroundContext];
然后,始终在 AppDelegate
中,您可以将更改与您编写的方法合并:
- (void)backgroundContextDidSave:(NSNotification *)notification {
// Make sure we're on the main thread when updating the main context
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(backgroundContextDidSave:)
withObject:notification
waitUntilDone:YES];
return;
}
// merge in the changes to the main context on the main thread
[[NSManagedObjectContext defaultContext] mergeChangesFromContextDidSaveNotification:notification];
}
该代码执行以下步骤:
- 首先检查您是否在主线程中运行。
- 由于您注册的通知可能来自线程与主选择器不同,您需要在主线程。
- 最后执行与包含您在后台所做的更改。
完成后,您可以看到主上下文已使用另一个上下文中所做的更改进行了更新。
编辑
也许您也可以尝试将waitUntilDone
更改为"是"。
希望对您有所帮助。
您正在混合两个上下文。这段代码可能是坏的:
record = [Record findFirstWithPredicate:recordPredicate];
我假设这在不同的上下文中找到记录,而不是您的背景上下文。您应该将其更改为如下所示的内容:
record = [Record findFirstWithPredicate:recordPredicate inManagedObjectContext:backgroundContext];