【问题标题】:UIManagedDocument nested ContextsUIManagedDocument 嵌套上下文
【发布时间】:2012-04-10 11:07:30
【问题描述】:

我一直在阅读苹果文档,但仍然有一个问题,我找不到答案。我有一个 UIManagedDocument 对象,它有两个嵌套的上下文——一个在主线程上的子上下文和一个在私有线程上的父上下文。接下来,我有一个服务器端。因此,当数据从服务器到达时,我想将其插入到后台线程上的托管文档中。

是否线程安全,要创建一个异步队列,在那里创建一个 NSManagedObjectContext 并将其设置为在主线程中创建的父 UIManagedDocument 的子上下文?

dispatch_queue_t fetchQ = dispatch_queue_create("Data fetcher", NULL);
dispatch_async(fetchQ, ^{
     //here goes some code for downloading data from the server

    NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [backgroundContext setParentContext:self.eventDatabase.managedObjectContext]; // is this thread safe?

    //some code for creating objects in backgroundContext

    NSLog(@"inserting data in background thread");


});
dispatch_release(fetchQ);

换句话说 - 分配给在主线程上创建的私有线程父级上创建的上下文是否线程安全?

【问题讨论】:

    标签: iphone core-data nsmanagedobjectcontext uimanageddocument


    【解决方案1】:

    您正在使用私有并发类型。这意味着,您应该在自己的队列上运行代码(通过 performBlock)。所以,如果你想这样做,你应该这样做......

    NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    backgroundContext.parentContext = self.eventDatabase.managedDocument;
    backgroundContext.performBlock:^{
        //here goes some code for downloading data from the server
        //some code for creating objects in backgroundContext
    
        NSLog(@"inserting data in background thread");
    
        // Calling save on the background context will push the changes up to the document.
        NSError *error = nil;
        [backgroundContext save:&error];
    
        // Now, the changes will have been pushed into the MOC of the document, but
        // the auto-save will not have fired.  You must make this call to tell the document
        // that it can save recent changes.
        [self.eventDatabase updateChangeCount:UIDocumentChangeDone];
    });
    

    如果您想自己管理队列,您可能应该使用限制 MOC,您应该使用 NSConfinementConcurrencyType 或标准 init 进行初始化,因为这是默认设置。然后,它看起来像这样......

    dispatch_queue_t fetchQ = dispatch_queue_create("Data fetcher", NULL);
    dispatch_async(fetchQ, ^{
        backgroundContext.parentContext = self.eventDatabase.managedDocument;
    
        //here goes some code for downloading data from the server
    
        NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] init];
    
        // Everything else is as in the code above for the private MOC.
    });
    dispatch_release(fetchQ);
    

    【讨论】:

    • 顺便说一句,不要忘记调用 [backgroundContext save:&error] 否则更改将不会被推送到父上下文。
    • 他为什么不直接使用UIManagedDocument的parentContex,这个context在后台运行?
    【解决方案2】:

    没有安德鲁 managedobjectcontext 不是线程安全的。为了实现你想要的,你必须创建一个子托管上下文,做你的事情,然后保存对子上下文和父上下文的更改。请记住,保存只会将更改提升一级。

    NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [addingContext setParentContext:[self.fetchedResultsController managedObjectContext]];
    
    [addingContext performBlock:^{
        // do your stuffs
        [addingContext save:&error];
    
        [parent performBlock:^{
            [parent save:&parentError];
        }];
    }];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-29
      • 2012-07-06
      • 1970-01-01
      • 2013-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多