2015-09-23 108 views
4

我有iOS中9核心數據有問題,我沒有在iOS的8的iOS 9核心數據線程

我有多個NSManagedObjectContext對象的環境。父context是併發類型NSMainQueueConcurrencyType,並且所有視圖控制器都有自己的子對象context。我使用這種系統的原因是因爲我想擁有更多獨立的contexts,並且只有在我決定完成時才合併它們。子context在私有隊列上,因爲它在後面的線程上工作,然後在父主線context上工作,父主線程將更改傳播到數據庫並在主線程上完成它所需的工作。

所有這一切都很好,直到iOS 9。我得到的行爲是相當奇怪的。例如,當我添加A類型的新對象時,它會傳播到存儲。如果我在同一個vc上添加另一個類型爲A的對象,使用相同的context,但是從另一個按鈕,moc的performBlockAndWait:未被調用,並且我的應用凍結,控制檯中沒有任何消息。如果嘗試使用第一個按鈕,它會每次都通過。

- (BOOL)saveChildContext:(NSManagedObjectContext*)childContext 
{ 
[childContext performBlockAndWait:^{ 
    NSError* error; 

    [childContext save:&error]; 

    [_managedObjectContext performBlock:^{ 
     NSError* parentError; 
     [_managedObjectContext save:&parentError]; 
    }]; 
}]; 

}

如果我叫performBlock:,一切都在這兩種情況下的罰款。所以我想通了,這可能是由於一些錯誤的線程。另一方面,使用相同類型的對象相同的線程,但另一個按鈕,一切都很好。這讓我感到困惑,並且懷疑它與線程有關。

我的問題:

1)是否會對後面的線程子context對象,並有context是保存到數據庫,再返回到GUI上的主線,還是有更好的慣例的正確方法,並如果有的話,爲什麼?

2)代碼在iOS 8上工作。但是,它似乎不會輸入performBlockAndWait:方法。爲什麼有時這個塊不會被執行?是否有其他線程阻塞?如何找出這是否是這種情況?

+0

要解決您的按鈕的特定問題,您必須發佈顯示兩個按鈕之間區別的代碼。 – Mundi

+0

我認爲問題可能在於,因爲其他選項從未造成死鎖或其他任何事情。不知何故,我使用了兩種不同的上下文。我真的不知道我是如何設法建立由兩個不同的上下文獲取的兩個對象之間的關係。還有一點很奇怪的是,當我調用異步performBlock時,它仍然沒有問題地到達DB。 –

回答

0

我想通了(謝謝蒙迪),我的一個類初始化了自己的NSManagedObjectContext對象來獲取一些數據。後來我將從不同上下文中獲取的對象關聯起來。不知何故,我可以做到這一點,儘管它不應該是可能的,並且必須避免嘗試以這種方式連接對象。總是使用相同的上下文來處理它們之間有關係的對象。

所以,我結束了使用childContext = someObjet.managedObjectContext;獲得正確的上下文的參考,而不是childContext = [dbClient createChildContext];返回新的上下文。

+0

如果你發現我的答案有幫助,你至少應該對它投票。 – Mundi

+0

當然,對不起。再一次感謝你。我討厭當我沒有得到幫助某人的功勞;) –

1

在我看來,你的設置並不理想。爲什麼在視圖控制器中使用背景上下文?視圖控制器是UI界面,應該使用主要的上下文。

在您的代碼示例中,您正在使用後臺線程中的主要上下文,我認爲這是存在問題的。

這是一個很好的標準設置(包括iOS9)。

rootContext (Private Queue) --> saves to persistent store --> has child 
mainContext (Main Queue)  --> used in UI    --> has children 
workerContext (Private Queue) --> create at will to do background stuff 

通過這種方式保存到永久性存儲區總是會持續存在並始終在後臺進行。這非常安全並且表現良好。

我使用ad hoc工作環境例如用於從服務器檢索後將東西保存在背景隊列中,或處理可以取消的對象編輯(您只需放棄上下文)。保存工作者上下文將更新UI(因爲改變被「向上推」到可以通過例如NSFetchedResultsControllerDelegate方法或NSNotificationCenter進行響應的主要上下文)。

+0

非常感謝您的意見和建議。正如我所說的,我想在另一個線程上執行一些後臺任務,爲GUI保留主線程。只能使用其他線程是一種解決方案嗎?如果我總是在主線程上通知GUI dispaching消息,我可能根本不會使用主線程進行數據工作。它是否正確? –

+0

是的。這也被封裝在我的答案中。 – Mundi

+0

是的,你說得對。如果父上下文位於主線程上,它會更新GUI,但是如果使用DB需要做很多工作,那麼在主線程上需要一些時間。另一方面,如果這個耗時的操作在其他線程上,它可以完成它的工作,並且在完成之後,它可能只是通知主線程,對吧? –