在后台線程上保存到CoreData Context

[英]Saving into CoreData Context on background thread


I am struggling with this for some time now and Apple's documentation and SO did not help so far. I was using ManagedObjectContext on a UIManagedDocument and the code below worked fine. I then decided to use Apple's template for CoreData in AppDelegate, so model, persistent store coordinator and context is created in AppDelegate. Fetching with AppDelegate's context is no problem, but background saving is an issue. I should have local context on the thread I am saving and as per Apple to have same persistance store coordinator. But the code below does not actually save the data. Can someone here please advise? Thank you.

我現在正在努力解決這個問題,到目前為止Apple的文檔和SO都沒有幫助。我在UIManagedDocument上使用ManagedObjectContext,下面的代碼運行正常。然后我決定在AppDelegate中使用Apple的CoreData模板,因此在AppDelegate中創建了模型,持久性存儲協調器和上下文。使用AppDelegate的上下文獲取是沒有問題的,但是后台保存是一個問題。我應該在我保存的線程上有本地上下文,並且根據Apple有相同的持久性存儲協調器。但是下面的代碼實際上並沒有保存數據。有人可以請指教嗎?謝謝。

- (void)fetchAndPersist
{
    dispatch_queue_t ffetchQ = dispatch_queue_create("ForFetch", NULL);
    dispatch_async(ffetchQ, ^{

        NSManagedObjectContext *secureManagedObjectContext;
        NSPersistentStoreCoordinator *coordinator = [appDelegate persistentStoreCoordinator];
        if (coordinator != nil) {
            secureManagedObjectContext = [[NSManagedObjectContext alloc] init];
            [secureManagedObjectContext setPersistentStoreCoordinator:coordinator];
        }

        // find missing date
        DataManager *dataManager = [[DataManager alloc] init];
        NSDate *missingDate = [dataManager findMissingDateFromDate:selectedDate inContext:secureManagedObjectContext];

        if (missingDate) {
            // fetch and parse data
            DataFetcher *dataFetcher = [[dataFetcher alloc] init];
            NSDictionary *fetchResponse = [dataFetcher parseDataForDate:missingDate];

            // persist it in a block and wait for it
            [secureManagedObjectContext performBlock:^{
                DataStore *dataStore = [[DataStore alloc] init];
                BOOL parsingError = [dataStore persistData:fetchResponse inContext:secureManagedObjectContext];

                if (parsingError) {
                    // handle error
                } else {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        // perform on main
                        [self fetchAndPersist];
                    });
                }
            }];
        }
    });
}

2 个解决方案

#1


18  

Try to use parent / child contexts:

嘗試使用父/子上下文:

http://www.cocoanetics.com/2012/07/multi-context-coredata/

In the link above you can find a code sample.

在上面的鏈接中,您可以找到代碼示例。

#2


3  

Your crash occurs because your NSManagedObjectContext is using the older, obsolete thread confinement model for Core Data concurrency:

發生崩潰的原因是您的NSManagedObjectContext正在使用舊的,過時的線程限制模型來實現Core Data並發:

secureManagedObjectContext = [[NSManagedObjectContext alloc] init];

secureManagedObjectContext = [[NSManagedObjectContext alloc] init];

init is just a wrapper around initWithConcurrencyType: with the argument NSConfinementConcurrencyType. This creates the context using the thread confinement model, which cannot use performBlock: or performBlockAndWait:. Only contexts using the newer (not obsolete!) queue confinement model can use these methods, and have to use these methods for any access to the context or objects belonging to it. To create a context using queue confinement and a private queue:

init只是initWithConcurrencyType的一個包裝器:帶有參數NSConfinementConcurrencyType。這使用線程限制模型創建上下文,該模型不能使用performBlock:或performBlockAndWait:。只有使用較新(非過時!)隊列限制模型的上下文才能使用這些方法,並且必須使用這些方法來訪問屬於它的上下文或對象。使用隊列限制和專用隊列創建上下文:

secureManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];

secureManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];

If your code was migrated to using a private queue context you could also remove your serial dispatch queue, as the private queue context provides equivalent functionality.

如果您的代碼已遷移到使用專用隊列上下文,則還可以刪除串行調度隊列,因為專用隊列上下文提供了相同的功能。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2013/09/15/729a71390cd807901148c955d8fa5c25.html



 
粤ICP备14056181号  © 2014-2020 ITdaan.com