核心数据-后台线程中的更新实体会自动更改主线程中的 NSManagedObject 而无需合并-为啥?
Posted
技术标签:
【中文标题】核心数据-后台线程中的更新实体会自动更改主线程中的 NSManagedObject 而无需合并-为啥?【英文标题】:Core Data - update entity in background thread automatically changes NSManagedObject in Main Thread without merging- why?核心数据-后台线程中的更新实体会自动更改主线程中的 NSManagedObject 而无需合并-为什么? 【发布时间】:2011-12-18 10:01:54 【问题描述】:我目前正在学习核心数据。 Core Data 很棒,但我无法解释后台线程中第二个托管对象上下文的行为。
我有一个名为 TestEntity 的实体,它有 2 个属性(testId 和 testDescription) 在主线程上,我获取 testId = 1 的实体并将这个托管对象存储到一个实例变量中。
NSEntityDescription *entityDescription = [NSEntityDescription
entityForName:@"TestEntity" inManagedObjectContext:self.managedObjectContext];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];
NSNumber *testId = [NSNumber numberWithInt:1];
NSPredicate *predicate = [NSPredicate predicateWithFormat:
@"testId == %@", testId];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *array = [self.managedObjectContext executeFetchRequest:request error:&error];
t1 = [[array objectAtIndex:0] retain];
TestThread *tt = [TestThread new];
NSOperationQueue *queue = [NSOperationQueue new];
[queue addOperation:tt];
[queue waitUntilAllOperationsAreFinished];
NSLog(@"%@", [t1 valueForKey:@"testDescription"]);
然后是使用一个名为 TestThread 的 NSOperationQueue 启动一个 NSOperation。 在这个 TestThread 的 main 方法中,我创建了第二个托管对象上下文,获取与主线程相同的实体 (testId = 1),更改 testDescription 属性并保存新的上下文而不会出现任何错误。
tgAppDelegate *delegate = [[NSApplication sharedApplication] delegate];
self.context = [[[NSManagedObjectContext alloc] init] autorelease];
[context setPersistentStoreCoordinator:delegate.persistentStoreCoordinator];
NSEntityDescription *entityDescription = [NSEntityDescription
entityForName:@"TestEntity" inManagedObjectContext:self.context];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];
// Set example predicate and sort orderings...
NSNumber *testId = [NSNumber numberWithInt:1];
NSPredicate *predicate = [NSPredicate predicateWithFormat:
@"testId == %@", testId];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *array = [context executeFetchRequest:request error:&error];
TestEntity *t1 = [array objectAtIndex:0];
t1.testDescription = @"abc";
[context save:&error];
if (error)
// do something
我无法解释自己的行为是,NSLog 输出之后
[queue waitUntilAllOperationsAreFinished];
具有在我的后台线程中更新的相同字符串值。
abc
我对核心数据和多线程的理解是我必须在上下文之间进行显式合并。 在我的测试应用中没有合并。
谁能解释为什么会这样?
【问题讨论】:
【参考方案1】:默认情况下,获取请求会将对象作为错误返回,因此在您访问它之前不会实际加载它们的内容(您可以在this link 下了解有关错误的更多信息)。
要查看您的预期行为,请在启动第二个线程之前尝试记录 t1.testDescription 的原始值。
你也可以设置
self.context.returnObjectsAsFaults = NO;
但这可能会对您的应用程序的内存占用产生负面影响。
【讨论】:
谢谢,您的链接帮助我理解了这一点以上是关于核心数据-后台线程中的更新实体会自动更改主线程中的 NSManagedObject 而无需合并-为啥?的主要内容,如果未能解决你的问题,请参考以下文章
iOS 在后台保存主线程 NSManagedObjectContext 更改