GCD和childcontext的Coredata并发无效访问/无法访问CDSnapshot_Entity

时间:2015-09-02 03:50:27

标签: ios multithreading core-data concurrency grand-central-dispatch

我正在尝试创建一个生成随机财务数据的后台线程。它使用childMOC和blockandwait进行插入和保存。 它通常可以工作但偶尔崩溃,尤其是更大的数据集。我猜这可能是因为内存分配/释放问题?

对我做错了什么的想法?

  1. 主要背景声明

    lazy var managedObjectContext: NSManagedObjectContext? = {
    let coordinator = self.persistentStoreCoordinator
    if coordinator == nil {
        return nil
    }
    var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
    managedObjectContext.persistentStoreCoordinator = coordinator
    return managedObjectContext }
    
  2. 获取MainMOC的副本并创建用于后台编写的PrivateMOC

    let mainMOC = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext let privateMOC = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType) privateMOC.parentContext = mainMOC

  3. 调用线程的主要功能

    iDataManager.setupManager()
    iDataManager.preloadDatabase()
    //3. load data from coreData
    iDataManager.loadListing()
    
    //TODO: swap in load code
    let loaderQueue = dispatch_queue_create("com.invest.serial.queue", DISPATCH_QUEUE_SERIAL)
    
    dispatch_async(loaderQueue, {
        //does not account for the market listing
        for var index = 0; index < self.iDataManager.dmStockListings.count; ++index {
            self.iDataManager.preloadPrice(index)
    
            dispatch_async(dispatch_get_main_queue(), {
                self.loadingViewController.updateProgressIndicator(index, total: self.iDataManager.dmStockListings.count)
            })
    
        }
        dispatch_async(dispatch_get_main_queue(), {
            self.loadingViewController.progressLabel.text = "Loading Done!"
            self.iDataManager.saveChanges()
    
            //5. init viewControllers as Panels
            AppSettings().delay(0.2, closure: {
                self.setupViewControllers()
            })
         })
    })
    
  4. 生成价格并调用privateMOC块

        let currentStock : MOStockListing
            currentStock = dmStockListings[index]
    

    //声明为var dmStockListings:[MOStockListing] = []并包含mainContext中的所有MOStockListing

    var error : NSError?
    var stockPrices : [MOPrice] = []
    var price : MOPrice
    
    //check coredata if there are prices
    var fetchRequest = NSFetchRequest(entityName: "MOPrice")
    let sortDescriptor = NSSortDescriptor(key: "priceDate", ascending: true)
    fetchRequest.sortDescriptors = [sortDescriptor]
    
    let predicate = NSPredicate(format: "stock == %@", currentStock)
    fetchRequest.predicate = predicate
    
    stockPrices = privateMOC?.executeFetchRequest(fetchRequest, error: &error) as! [MOPrice]
    
    if stockPrices.count == 0 {
        //create daily, weekly and monthly
        //set flag for update
        dmDatabaseState = .UpdateFlag
    
        privateMOC.performBlockAndWait({
    
            self.generateDemoPrices(currentStock)
    
            var errorPointer = NSErrorPointer()
            self.privateMOC.save(errorPointer)
    
        })
    
    }
    
  5. 生成价格函数:迭代1000天以创建随机值。也在mainMOC中插入。一般都有效。但是我应该使用privateMoc吗?

                //load prices
            price = NSEntityDescription.insertNewObjectForEntityForName("MOPrice", inManagedObjectContext: privateMOC!) as! MOPrice
    
            price.setValue(close, forKey: "priceClose")
            price.setValue(high, forKey: "priceHigh")
            price.setValue(open, forKey: "priceOpen")
            price.setValue(low, forKey: "priceLow")
            price.setValue(volume, forKey: "priceVolume")
            price.setValue(dateValue, forKey: "priceDate")
            price.setValue(change, forKey: "priceChange")
    
            price.stock = currentStock
    
  6. 评论:我想我需要让privateMOC自己加载所有实体并执行插入然后调用保存。作为mainMOC的孩子,我不需要进行任何上下文合并,这是正确的吗?

    编辑:这似乎有效。我还发现在主线程上保留额外的处理使加载时间更快。我使用privateMOC.blockandwait只写入coredata。 我修改了上面的代码以反映这一点。

0 个答案:

没有答案