Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/109.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios NSManagedObjectContext和队列_Ios_Objective C_Multithreading_Nsmanagedobjectcontext_Nsoperationqueue - Fatal编程技术网

Ios NSManagedObjectContext和队列

Ios NSManagedObjectContext和队列,ios,objective-c,multithreading,nsmanagedobjectcontext,nsoperationqueue,Ios,Objective C,Multithreading,Nsmanagedobjectcontext,Nsoperationqueue,在与主运行中心和队列打了一段时间交道后,我仍然不确定我是否理解如何正确使用主运行中心和队列。我将分别介绍每种类型的主运行中心: NSMainQueueConcurrencyType 这个其实很简单。它说必须在主队列上运行。这可以通过使用[context performBlock:block]或直接使用它来实现 如果代码在主线程上执行,则可以直接调用主队列样式上下文上的方法,而不是使用基于块的API NSConfinementConcurrencyType 除了创建上下文的线程外,任何线程都不会使

在与主运行中心和队列打了一段时间交道后,我仍然不确定我是否理解如何正确使用主运行中心和队列。我将分别介绍每种类型的主运行中心:

NSMainQueueConcurrencyType

这个其实很简单。它说必须在主队列上运行。这可以通过使用
[context performBlock:block]
或直接使用它来实现

如果代码在主线程上执行,则可以直接调用主队列样式上下文上的方法,而不是使用基于块的API

NSConfinementConcurrencyType

除了创建上下文的线程外,任何线程都不会使用该上下文

这对队列,甚至连不承诺始终使用同一线程的串行队列意味着什么

NSPrivateQueueConcurrencyType

上下文创建并管理专用队列

我是否必须通过
[context performBlock:block]
将此队列用于所有处理

我可以直接从一个串行队列中使用它吗?我以类似于
NSMainQueueConcurrencyType
的方式定义了该队列

或者换句话说,执行以下操作是否安全:

NSOperationQueue *workQueue = [[NSOperationQueue alloc] init];
workQueue.maxConcurrentOperationCount = 1;

[workQueue addOperationWithBlock:^{
    // It just creates a new MOC with some parent
    _context = [SUDataManager createChildContext]; 
    // .... Do things with context without [_context performBlock:block]...
}];

使用块

我将建议做完全相反的事情:始终使用块方法,原因如下:

该块保证每个操作都是计划的,并在下一个操作之前完成。 这有点像在if(){}之后使用{and}。这种做法可以确保您不会因源格式设置而受到错误的约束,并且您正在编写和执行您想要的内容

如果您将块与
performBlockAndWait
组合,您就不能参加比赛。因此,除非你有充分的理由不这样做,并且有大量的时间来空闲和调试iCloud,否则每次我都会选择健壮的方法

例如:

[self.mainMOC performBlockAndWait:^{
    __strong myClass * strongSelf = weakSelf;
    if(strongSelf) {
        if( [strongSelf.mainMOC hasChanges]) {
            NSError *error = nil;
            [strongSelf.mainMOC save:&error];
        }
    }
}];
选择哪种并发类型

  • 主线程:使用
    NSMainQueueConcurrencyType
  • 任何其他线程:使用`NSPrivateQueueConcurrencyType
  • 从技术上讲,您可以将
    NSConfinementConcurrencyType
    用于主线程,并且可能仅用于遗留线程,但在MainQueue PrivateQueue模型中不需要它

    如何设置后台线程

    在后台线程中,设置父上下文。如果这样做,并遵循
    performBlockAndWait
    建议,则所有操作都将按顺序进行,并在执行下一个操作之前完成,从而确保数据的稳定性。iCloud不是一个你想破坏的环境

    self.privateMOC = [[NSManagedObjectContext alloc]
        initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [self.privateMOC setParentContext:mainMOC];
    [self.privateMOC setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
    

    如果使用
    NSConfinementConcurrencyType
    ,则只能直接发送消息,该类型仅为向后兼容而存在。此外,可以将基于队列的并发类型与
    performBlock:
    performBlockAndWait:
    结合使用上下文。最后,这可能是最关键的部分:如果使用
    NSOperation
    ,则必须在main(对于串行队列)或start(对于并发队列)中创建上下文。在您的示例中,
    [SUDataManager createChildContext]
    必须位于*workQueue的-start,而不是它的
    NSOperation
    。实际上,您可以直接从主线程发送消息(NSPrivateQueueConcurrencyType)。关于
    NSOperation
    ,文档中的这一部分似乎讨论了
    NSConfinementConcurrencyType
    ,而不是
    NSPrivateQueueConcurrencyType
    。无论如何,这是不清楚的。大多数人肯定同意文件的模糊性。是的,你可以从任何你想要的地方发送消息。文档对两个帐户都很清楚:(1)
    NSConfinementConcurrencyType
    是否存在……以实现向后兼容性;(2)您使用上下文,将基于队列的并发类型与
    performBlock:
    performBlockAndWait:
    结合使用。将这两句话组合起来,只使用
    NSMainQueueConcurrencyType
    NSPrivateQueueConcurrencyType
    和块来满足您的所有需要。因此,对于“它安全吗”这个问题,我倾向于“它可能有效,但我不会这么做”。下面的答案是否提供了解决方案?