NSManagedObject 总是在同一个 ManagedObjectContext 上创建
Posted
技术标签:
【中文标题】NSManagedObject 总是在同一个 ManagedObjectContext 上创建【英文标题】:NSManagedObject is always being created on the same ManagedObjectContext 【发布时间】:2012-10-31 05:43:18 【问题描述】:我已经处理这个问题一段时间了 (https://***.com/questions/12982012/unit-testing-core-data-to-many-relationship),但我终于能够辨别真正的问题是什么。无论我尝试做什么,我都有一个始终在主 managedObjectContext 上创建的实体。我的所有其他实体都工作正常,但这个实体似乎特别有问题。自从我用新名称提出上一个问题后,我已经重建了整个数据模型,但问题仍然存在。我尝试搜索并看到一个问题(Why do some of my core data objects have managedObjectContext set to nil?)引用了一个类似的问题,他被设置为 nil。
我要做的是创建一个新的上下文来导入数据以在后台运行。
这里是解释一切的日志
首先是[self managedObjectContext]。我正在使用它从 AppDelegate 中调用 MOC,它的代码直接来自基于 Apple 的 Core Data 应用程序。
- (NSManagedObjectContext *)managedObjectContext
return [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
在 LoginVC 中使用 main managedObjectContext
Deal *testdeal = [NSEntityDescription insertNewObjectForEntityForName:@"Deal" inManagedObjectContext:[self managedObjectContext]];
TriageAnswer *testtriage = [NSEntityDescription insertNewObjectForEntityForName:@"TriageAnswer" inManagedObjectContext:[self managedObjectContext]];
NSLog(@"moc is %@", [self managedObjectContext]);
NSLog(@"testdeal.moc = %@", testdeal.managedObjectContext);
NSLog(@"testtriage.moc = %@", testtriage.managedObjectContext);
2012-10-30 17:51:19.134 myApp[6507:11603] moc is <NSManagedObjectContext: 0x84ace20>
2012-10-30 17:51:19.134 myApp[6507:11603] testdeal.moc = <NSManagedObjectContext: 0x84ace20>
2012-10-30 17:51:19.134 myApp[6507:11603] testtriage.moc = <NSManagedObjectContext: 0x84ace20>
在我的更新类中使用多个 managedObjectContexts。 importContext2 只是我出于测试目的提出的一个。
NSManagedObjectContext *importContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[importContext setParentContext:[self managedObjectContext]];
[importContext setUndoManager:nil];
NSManagedObjectContext *importContext2 = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
[importContext2 setParentContext:importContext];
Deal *importDeal = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([Deal class]) inManagedObjectContext:importContext];
Deal *importDeal2 = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([Deal class]) inManagedObjectContext:importContext2];
Deal *importDeal3 = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([Deal class]) inManagedObjectContext:[self managedObjectContext]];
TriageAnswer *importTriage = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([TriageAnswer class]) inManagedObjectContext:importContext];
NSLog(@"importcontext is %@", importContext);
NSLog(@"importcontext 2 is %@", importContext2);
NSLog(@"self managedobjectcontext is %@", [self managedObjectContext]);
NSLog(@"deal is %@", importDeal.managedObjectContext);
NSLog(@"deal2 is %@", importDeal2.managedObjectContext);
NSLog(@"deal3 is %@", importDeal3.managedObjectContext);
NSLog(@"triage moc is %@", importTriage.managedObjectContext);
2012-10-30 17:54:16.571 myApp[6507:11603] importcontext is <NSManagedObjectContext: 0x84b3ce0>
2012-10-30 17:54:20.403 myApp[6507:11603] importcontext 2 is <NSManagedObjectContext: 0x14163890>
2012-10-30 17:54:22.876 myApp[6507:11603] self managedobjectcontext is <NSManagedObjectContext: 0x84ace20>
2012-10-30 17:54:24.296 myApp[6507:11603] deal is <NSManagedObjectContext: 0x84ace20>
2012-10-30 17:54:25.017 myApp[6507:11603] deal2 is <NSManagedObjectContext: 0x84ace20>
2012-10-30 17:54:25.646 myApp[6507:11603] deal3 is <NSManagedObjectContext: 0x84ace20>
2012-10-30 17:56:34.221 myApp[6507:11603] triage moc is <NSManagedObjectContext: 0x84b3ce0>
【问题讨论】:
不确定这是否相关,但“核心数据最佳实践”WWDC 视频指出父上下文必须使用其中一种队列并发类型,而主 moc 则不是这种情况在标准核心数据模板 iirc 中设置。 这是真的(我在其他地方读到过)。我其实已经把它改成了[[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
除此之外,标准的核心数据模板
【参考方案1】:
我会自己回答这个问题,以防万一有人犯了我犯的错误。但是我所有的 NSManagedObject 子类都有为它们创建的类别,在某些时候我天真地把
- (NSManagedObjectContext *)managedObjectContext
return [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
在我的类别中。我正在制作另一种方法来执行自定义获取请求,并认为我需要它来访问 MOC,我显然不需要。实现它是完全可以接受的,因此它被埋在类别中而被遗忘了。因此,每当我的 Deal 对象试图访问它的 MOC 时,该调用就会被覆盖并返回主 MOC。
【讨论】:
以上是关于NSManagedObject 总是在同一个 ManagedObjectContext 上创建的主要内容,如果未能解决你的问题,请参考以下文章
核心数据:访问 NSManagedObject 属性时应用程序崩溃
从 NSManagedObject 中检索 NSManagedObjectContext
NSManagedObject 的日期与 NSDate 的 Xcode 9 构建问题
如何在 CoreData 的代码中设置 NSManagedObject 与另一个 NSManagedObject 或它们的堆栈的关系?