我正在接近并发吗?

时间:2015-05-31 18:38:03

标签: ios objective-c core-data concurrency

我想知道是否有人可以指出我是否正确使用并发性的正确方向。我发现目前代码非常笨拙且几乎不直观。出于演示目的,请注意CoreData架构如Marcus Zarra在其文章http://martiancraft.com/blog/2015/03/core-data-stack/中所述。由于操作可能需要很长时间,我希望整个过程在后台线程中完成。

 NSManagedContext *context = [[NSManagedContext alloc] initWithConcurrency:NSPrivateConcurrencyQueue];
 context.parentContext = [[CoreDataController sharedDispatch] managedObjectContext];
 [context performBlock: ^{
 NSManagedObject *someManagedObject = [[context executeFetchRequest:request error:nil] firstObject];
 NSString *resultFromLongOperation = [self someLongOperation:someManagedObject];
 [self doSomething];
 BOOL anotherResultFromLongOperation = [self aDifferentLongOperation:someManagedObject];
 }];

因此,从这个简短的例子中,我们可以看到我正在操作变量some​​ManagedObject,它是NSManagedObject类型,因此必须在Apple规定的performBlock / performBlockAndWait中使用。我应该在上下文中传递一些LongOperation和一个不同的LongOperation吗?如果我不这样做,那是不是意味着我必须创建另一个子上下文并在performBlock / performBlockAndWait中执行函数所做的任何操作并使用__block类型返回结果?如果someLongOperation的结果影响了不同的LongOperation的响应,那么该怎么办?我还在为这种情况正确构建我的代码吗?

非常感谢先进!

1 个答案:

答案 0 :(得分:0)

我不久前在同一个问题上苦苦挣扎。

我寻找最佳练习场景并发现:

  • 正如您所说,您确实不应违反Apple设定的一个上下文/线程规则。
  • 您通常应该使用具有长时间运行操作的完成块或通知,无论是为了不冻结UI,还是仅为了清晰的代码。
  • 使用完成块时,可以在长时间运行的操作函数(someLongOperation)中创建子上下文,并随意执行任何操作。
  • 如果您的结果是NSString,那么您应该没有问题,因为它不是NSManagedObject而且它没有绑定到任何一个上下文。
  • 如果结果是NSManagedObject,则应将其NSManagedObjectID传递给完成块(使用[managedObject objectID]方法)。
  • 如果您创建了一个新实体并且它还没有对象ID,您可以使用上下文的方法obtainPermanentIDsForObjects

基本上,如果它们都使用相同的线程,则可以为每个长时间运行的操作使用相同的上下文。在我的情况下,它们并不一定如此,所以我为每个长时间运行的操作创建一个新的子上下文,以确保(创建一个新的子上下文是一个非常快速的操作,因此性能不是问题)