我有以下对象树:
- Name Project
- Users nil
- John nil
- Documents nil
- Acme Project Acme Project <--- User selects a project
- Proposal.doc Acme Project
- 12:32-12:33 Acme Project
- 13:11-13:33 Acme Project
- ...thousands more entries here...
>用户可以为一个项目分配一个组.所有后代都被设置为该项目.
>这会锁定主线程,所以我使用NSOperations.
>我正在使用Apple批准的这种方法,看NSManagedObjectContextDidSaveNotification并合并到主要的上下文中.
问题
我的保存已经失败,出现以下错误:
保存前无法处理挂起的更改. 100次尝试后,上下文仍然很脏.通常这个递归的脏污是由一个坏的验证方法,-willSave或通知处理程序引起的.
我试过的
我已经把我的应用程序的所有复杂性都消除掉了,并且做了我能想到的最简单的项目.并且错误仍然发生.我试过了:
>将队列上的最大操作数设置为1或10.
>调用refreshObject:mergeChanges:在NSOperation子类的几个点.
>在受管对象上下文中设置合并策略.
>建立和分析.它变空了
我的问题
没有我的应用程序崩溃,我如何在NSOperation中设置关系?当然这不是Core Data的限制吗?它可以?
下载我的项目:http://synapticmishap.co.uk/CDMTTest1.zip
主控制器
- @implementation JGMainController
- -(IBAction)startTest:(id)sender {
- NSManagedObjectContext *imoc = [[NSApp delegate] managedObjectContext];
- JGProject *newProject = [JGProject insertInManagedObjectContext:imoc];
- [newProject setProjectName:@"Project"];
- [imoc save];
- // Make an Operation Queue
- NSOperationQueue *queue = [[NSOperationQueue alloc] init];
- [queue setMaxConcurrentOperationCount:1]; // Also crashes with a higher number here (unsurprisingly)
- NSSet *allTrainingGroupsSet = [imoc fetchAllObjectsForEntityName:@"TrainingGroup"];
- for(JGTrainingGroup *thisTrainingGroup in allTrainingGroupsSet) {
- JGMakeRelationship *makeRelationshipOperation = [[JGMakeRelationship alloc] trainGroup:[thisTrainingGroup objectID] withProject:[newProject objectID]];
- [queue addOperation:makeRelationshipOperation];
- makeRelationshipOperation = nil;
- }
- }
- // Called on app launch.
- -(void)setupLotsOfTestData {
- // Sets up 10000 groups and one project
- }
- @end
进行关系操作
- @implementation JGMakeRelationshipOperation
- -(id)trainGroup:(NSManagedObjectID *)groupObjectID_ withProject:(NSManagedObjectID *)projectObjectID_ {
- appDelegate = [NSApp delegate];
- imoc = [[NSManagedObjectContext alloc] init];
- [imoc setPersistentStoreCoordinator:[appDelegate persistentStoreCoordinator]];
- [imoc setUndoManager:nil];
- [imoc setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(mergeChanges:)
- name:NSManagedObjectContextDidSaveNotification
- object:imoc];
- groupObjectID = groupObjectID_;
- projectObjectID = projectObjectID_;
- return self;
- }
- -(void)main {
- JGProject *project = (JGProject *)[imoc objectWithID:projectObjectID];
- JGTrainingGroup *trainingGroup = (JGTrainingGroup *)[imoc objectWithID:groupObjectID];
- [project addGroupsAssignedObject:trainingGroup];
- [imoc save];
- trainingGroupObjectIDs = nil;
- projectObjectID = nil;
- project = nil;
- trainingGroup = nil;
- }
- -(void)mergeChanges:(NSNotification *)notification {
- NSManagedObjectContext *mainContext = [appDelegate managedObjectContext];
- [mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
- withObject:notification
- waitUntilDone:YES];
- }
- -(void)finalize {
- appDelegate = nil;
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- imoc = nil;
- [super finalize];
- }
- @end
- @implementation NSManagedObjectContext (JGUtilities)
- -(BOOL)save {
- // If there's an save error,I throw an exception
- }
- @end
数据模型
更新1
我已经尝试了一些,即使没有合并,仍然抛出异常.修改关系后,只需将管理对象上下文保存在另一个线程就足够了.
我有一个共享的持久性商店协调员与应用程序代表.我已经尝试为线程使用与数据存储相同的URL创建一个单独的NSPersistentStoreCoordinator,但是Core Data抱怨.
解决方法
startTest从一个按钮调用(是IBAction,假设按钮点击)在主线程上
>您的for循环使用初始化程序trainGroup创建一个JGMakeRelationship对象:withProject:(这应该称为init,并且可能调用super,但这不会导致此问题).
>在主线程中,在操作中创建一个新的托管对象上下文.
>现在操作队列从工作线程调用操作“main”方法(在这里放置一个断点,你会看到它不在主线程上).
>您的应用程序变得繁荣,因为您已经从与其创建的线程不同的线程访问了受管对象上下文.
解:
在操作的main方法中初始化托管对象上下文.