6

很多人问过一个类似标题但目的却截然不同的问题:

如果您允许来自其他类的方法调用(默认情况下,每个类都允许), CoreData要求您跟踪当前队列、当前线程和当前 NSOperationQueue(如果您是 NSOperation)。对此没有“可能”:这是一个硬性要求。

这很好,而且通常很容易确保:

NSAssert( [NSThread currentThread].isMainThread || myPrivateQueue == dispatch_get_current_queue(), @"You tried to call this method from an external thread, or a queue other than my internal private queue. That's not legal, and will cause data corruption" );

...除了 Apple 已经弃用 dispatch_get_current_queue() 之外,显然“因为人们滥用它来解决 GCD 中缺少的功能/他们不理解的 GCD 位”。

注意:我对 dispatch_get_current_queue() 的使用似乎是正确且非滥用的,从 Apple 的标题评论来看:重点是我正在检查队列是我创建的私有队列(Apple 声称这是可以接受的用法) .

撇开仅仅因为其实现中存在缺陷而弃用某些东西的智慧:( ...有没有人找到解决方法来解决这个问题被Apple删除。特别是:使用CoreData,您必须跟踪队列-是否有另一种方法可以做到这一点?

(这很重要,因为:使用 CoreData,如果你允许某些东西意外调用这样的方法,你不会得到“崩溃”,你会得到“数据损坏,这将在未来某个时候出现,但为时已晚要解决这个问题”)

4

2 回答 2

4

performBlock始终在正确的线程中运行它。只需使用:

[yourManagedObjectContext performBlock:^{
//do your stuff here
}];

您不再需要跟踪当前上下文,因为您的 MOC 知道哪个线程首先触发此 MOC。当你使用performBlockperformBlockAndWait你是安全的。

于 2013-08-29T12:28:56.210 回答
0

在我的具体情况下,我将所有 performBlock 调用替换为:

  1. 将所有 CoreData 操作移动到单个类
  2. 创建一个私有 dispatch_queue
  3. 将我所有的内部呼叫合并为一个呼叫
  4. 单个调用将自身包装在 dispatch_async( (私有内部队列) ) 中
    1. ...它在调度中做的第一件事是“if(self.privateMOC == nil)”...并创建本地 MOC,保证 MOC 只在那个队列上被访问和创建

发生了两件事:

  1. 互斥锁/锁挂起都消失了(尽管这可能是巧合 - 如果结果证明锁仍然陷入僵局,我会在稍后报告)
  2. 性能似乎明显优于 performBlock:在任何地方都使用
    1. 注意:我们有很多 performBlock 调用,并且经常这样做(敏感数据需要以中等高频率更改 CoreData MOC 内容)。我不知道这在普通应用程序中是否会有明显差异

...所以,就目前而言,就我的目的而言:这已被证明是一个很好的解决方案。我不相信这是对这个问题的“正确”通用答案,但是......我推荐给那些发现“performBlock”不像看起来那么灵丹妙药的人。

于 2013-08-29T16:54:17.090 回答