iOS CoreData多线程(一)☂️

CoreData与线程安全

CoreData不是线程安全的,对于ManagedObject以及ManagedObjectContext的访问都只能在对应的线程上进行,而不能跨线程操作。

  • 对于多个线程,每个线程使用自己独立的ManagedContext。
  • 对于线程间需要传递ManagedObject的,传递ManagedObject ID,通过objectWithID或者existingObjectWithID来获取。
  • 对于PSC(NSPersistentStoreCoordinator)来说,多个context可以共享一个NSPersistentStoreCoordinator。

对于数据量很大的APP来说,解决多线程的问题通常是通过主线程一个mainContext处理UI相关的,后台一个线程的backgroundContext负责耗时操作的,操作完成后通知主线程。使用CoreData的并行主要有两种方式

  • Notification
  • child/parent context

并行的解决方案之Notification

  • NSManagedObjectContextObjectsDidChangeNotification 当Context中的变量改变时候触发。

  • NSManagedObjectContextDidSaveNotification 在一个context调用save完成以后触发。注意如果在另一个线程响应通知,要调用mergeChangesFromContextDidSaveNotification来合并。

简单来说,就是不同的线程使用不同的context进行操作,当一个线程的context发生变化后,利用notification来通知另一个线程Context,另一个线程调用mergeChangesFromContextDidSaveNotification来合并变化。
为什么说这样做的效率更高?
这样做两个context共享一个持久化存储缓存,而且这么做互斥锁只需要在sqlite级别即可。设置当主线程只读的时候,都不需要锁。

并行的解决方案之child/parent context

ChildContext和ParentContext是相互独立的。只有当ChildContext中调用Save了以后,才会把这段时间来Context的变化提交到ParentContext中,ChildContext并不会直接提交到NSPersistentStoreCoordinator中, parentContext就相当于它的NSPersistentStoreCoordinator。
child/parent context的

结构图如下 :


iOS CoreData多线程(一)☂️_第1张图片
child/parent context模式

这需要注意:
通常主线程context使用NSMainQueueConcurrencyType,其他线程childContext使用NSPrivateQueueConcurrencyType.
child和parent的特点是要用Block进行操作,performBlock,或者performBlockAndWait,保证线程安全。这两个函数的区别是performBlock不会阻塞运行的线程,相当于异步操作,performBlockAndWait会阻塞运行线程,相当于同步操作。这次不需要监听变化,因为变化会自动提交到mainContext。

self.privateContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [self.privateContext setParentContext:self.mainContext];
    //执行耗时的操作

    //执行完毕
    [self.privateContext performBlock:^{
        NSError * error = nil;
        if ([self.privateContext hasChanges]) {
            [self.privateContext save:&error];
        }
    }];

参考: iOS CoreData详解(五)多线程

你可能感兴趣的:(iOS CoreData多线程(一)☂️)