核心数据:在后台加载数据并保存

时间:2015-07-23 10:28:34

标签: ios objective-c multithreading swift core-data

我需要从csv加载大量数据 为了避免UI冻结,我必须在不同的线程上执行此操作。

@objc(Person)
class Person: NSManagedObject {
    @NSManaged var name: String?
}

func createDummies(completion : (success : Bool, result: [Person]?, error : NSError?) -> Void) {
    let qualityOfServiceClass = QOS_CLASS_BACKGROUND
    let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
    dispatch_async(backgroundQueue, { () -> Void in
       var res: [Person] = []
       for var i = 0; i < 10; ++i {
          let p = Person.MR_CreateEntity
          res.append(p)
       }
       completion(success: true, result: p, error: nil)
    })        
}

func loadDummies() {
   createDummies({ (success, result, error) -> Void in
      MagicalRecord.saveWithBlock { (m: NSManagedObjectContext!) -> Void in
         let persons = Person.MR_findAll() as? [Person]
         println("block \(persons)")
      }
      let persons = Person.MR_findAll() as? [Person]
      println("out block \(persons)")

   } 
}

此代码产生一个奇怪的输出:

 block Optional([])
 out block Optional([ <Person: 0x7fd0224129e0> (entity: Person;] ..... etc)

因此,如果在此之后我在另一个视图控制器中调用Person.MR_FindAll,则结果为空数组。

有什么想法吗?我认为问题是在不同的线程中创建和保存实体:如果是这种情况,我该如何解决这个问题呢?

1 个答案:

答案 0 :(得分:1)

核心数据对象不是线程安全的!并且您不应该对核心数据的主要上下文进行大量更新/保存,它会冻结您的UI。如果您使用NSFetchResultController委托的子父上下文方法,那么如果您的背景上下文是UI上下文的子项,则UI上的数据将自动更新。 UI上下文应为NSMainQueueConcurrencyType类型,子(背景)上下文应为NSPrivateQueueConcurrencyType类型。NSManagedObjectContext具有performBlockAndWaitperformBlock方法应该执行获取和更新。