CoreData:只能在使用队列创建的NSManagedObjectContext上使用-performBlock :.

时间:2014-07-06 23:28:43

标签: ios objective-c core-data swift

我不确定这是怎么回事,但我可以使用一些帮助。每次用户在UITextField中输入文本时,我都会尝试在后台执行查询。我一直在阅读,看起来这就是我应该如何执行后台CoreData操作,但我不断收到此错误:

“只能在使用队列创建的NSManagedObjectContext上使用-performBlock:”

我用Google搜索了这个错误,但是每个解决方案都说我需要使用PrivateQueueConcurrentcyType创建我的上下文。不知道为什么会这样。也许这是新iOS中的一个错误?

let managedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = appDelegate.persistentStoreCoordinator
if !textField.text.isEmpty {
    manatedObjectContext.performBlock {
         let objectIDs = //query to get the object IDs

         appDelegate.managedObjectContext.performBlock {
             var objects = Object[]()

             for id in objectsIDs {
                 objects += appDelegate.managedObjectContext.objectWithID(id) as Object
             }

             self.searchResults = objects
             self.searchResultsTableView.reloadData()
         }
    }
}

编辑:我通过执行以下操作解决了我的问题:

  • 将私有managedObjectContext的父上下文设置为AppDelegate的主要上下文
  • 我删除了设置持久存储的行,因为在将父上下文设置为主上下文时不再需要它
  • 我还更改了创建主要上下文的默认实现,以使用MainQueueConcurrencyType显式创建它

2 个答案:

答案 0 :(得分:2)

从实际发布的应用中获取的示例,您应该使用 2 + MOC。

  1. 一个主线程
  2. 每个后台主题一个。
  3. 这允许后台线程安全地执行MOC操作,而不会存在相互冲突的风险。请注意辅助MOC如何使用-setParentContext:来引用主MOC。

    这个backgroundMOC在从后台线程创建和使用时是安全的,不会抛出错误。

    完成修改后,请在后台线程中执行保存:

    [backgroundMOC performBlockAndWait:^{
        if([backgroundMOC hasChanges]) {
            NSError * error;
            [backgroundMOC save:&error];
            // handle error
        }
    }];
    

    要创建上面示例中使用的两个MOC,您可以使用下面的代码(ObjC)

    对于主要帖子,请使用:

    @property(strong) NSManagedObjectContext * 
    
    - (NSManagedObjectContext *)mainMOC mainManagedObjectContext;
    {
        NSThread * currentThread = [NSThread currentThread];
        NSAssert([currentThread isMainThread], @"managedObjectContext invoked from %@",currentThread);
        if([currentThread isMainThread]) {
            if(!_mainManagedObjectContext) {
                NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    
                if(coordinator) {
                    _mainManagedObjectContext = [[NSManagedObjectContext alloc]
                                                 initWithConcurrencyType:NSMainQueueConcurrencyType];
                    [_mainManagedObjectContext setPersistentStoreCoordinator: coordinator];
                    [_mainManagedObjectContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
                }
            }
    
            return _mainManagedObjectContext;
        }
        return nil;
    }
    

    对于后台主题,请使用:

    - (NSManagedObjectContext *)threadMOCWithMainMOC:(NSManagedObjectContext *)mainMOC
    {
        NSManagedObjectContext * threadManagedObjectContext = [[NSManagedObjectContext alloc]
                                           initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [threadManagedObjectContext setParentContext:[self.db mainManagedObjectContext]];
        [threadManagedObjectContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
        return threadManagedObjectContext;
    }
    

答案 1 :(得分:0)

问题不在于您在所提供的代码中构建的MOC,而在于您从应用代理获得的MOC。我打赌这是用苹果提供的核心数据模板构建的......(非常不幸的是)仍然创建了默认限制类型的MOC ......

这就是它抱怨的......

appDelegate.managedObjectContext.performBlock {