2014-01-13 44 views
1

當前正在學習如何在多線程環境中使用核心數據;使用NSPrivateQueueConcurrencyType保存NSManagedObjectContext

因此,我創建了一個小型的項目有兩個NSManagedObjectContext:主NSManagedObjectContextNSMainQueueConcurrencyType進行讀取和其子NSManagedObjectContextNSPrivateQueueConcurrencyType創建/更新/刪除操作。

人們常常說,儲蓄與NSPrivateQueueConcurrencyType一個NSManagedObjectContext應通過performBlock:做到像這樣:

[context performBlock:^ 
{ 
    Book *mutableBook = [self getMutableVersionOfBook:book]; 

    [context deleteObject:mutableBook]; 

    [context save:nil]; 
}]; 

如果省略performBlock:會發生什麼,就像這樣:

Book *mutableBook = [self getMutableVersionOfBook:book]; 

[context deleteObject:mutableBook]; 

[context save:nil]; 

請問保存然後發生在保存被調用的線程上?如果不使用performBlock:會發生什麼?

+0

當你嘗試時發生了什麼? – Abizern

+0

@Abizem它保存數據;我主要好奇數據保存的方式,以及爲什麼它不是推薦的方法。 – MrJre

+0

在BooL * mutableBook行和delete行之後放置一個斷點,並查看是否在(Xcode - > Left Side-> 6th tab-> click CPU-> see below threads)上創建了一個新線程。你會知道這是否發生在新線程中。 – santhu

回答

4

私人隊列MOC只能通過-performBlock:-performBlockAndWait:來觸及。如果您以任何其他方式觸摸它,那麼您違反了核心數據的線程邊界規則,並且最終會導致數據損壞。

在某些情況下,這會導致應用程序崩潰,因爲違反該線程邊界是應用程序級錯誤。蘋果已經多次將這次崩潰關閉,現在它可能會或可能不會成爲崩潰狀態。在我看來,它應該是一直處於崩潰狀態。

作爲一般規則,我建議您使用線程受限MOC作爲主要MOC的子代,而不是使用私有MOC。雖然私人MOC很好用,但每個操作的結構都必須在一個塊中,並且您不能訪問結果NSManagedObject實例,除非在這些塊中有限制。最好是將一個操作放到一個隊列中,在該隊列中創建一個線程受限的MOC,然後使用更清晰的代碼,而不是不斷地跳入塊中(或者更糟的是創建巨大的不可維護的塊)。

最後。您正在通過nil-save:千萬不要那樣做。當你這樣做時,你正在隱藏一個潛在的問題。即使「這只是一個例子」,這是一個可怕的習慣,你應該立即打破它。即使在示例代碼中,傳入NSError並檢查錯誤。即使你只是將結果傳遞給NSLog,你至少也會避免一個驚喜。

+1

無論如何,爲'NSError **'參數傳遞'nil'是錯誤的。這是一個指針參數,所以'NULL'將是正確的,因爲少數情況下,你真的*不關心錯誤。 – alastair

+0

據我所知,孩子MOC仍然在小牛身上受到嚴重破壞(新插入的對象之間的關係在保存之前中斷。在保存之前獲得的PermissionIDsForObjects解決了問題,但這至少令人討厭)。你真的推薦使用它們嗎? –

+0

@fabricetruillotdechambrier:簡答題;是。他們更容易打架。邊緣不如其他選項鋒利。他們是最高性能的?不,但它們是多線程CD的更清晰的方式。如果您對其他解決方案感覺舒適/經驗豐富,那就去找他們吧,但我不建議他們向剛開始使用Core Data的開發人員推薦他們。 –

1

保存可能會發生在它被調用的線程上。後果是什麼?我們不知道實施情況,所以我們只能猜測。有時,託管上下文和託管對象的不正確使用可能會導致非常奇怪的行爲,甚至不會認爲這是由於線程錯誤造成的。

上下文和託管對象的所有工作必須在創建它們的線程或隊列上完成。基本上,對於傳統上下文和使用私有隊列併發類型的上下文來說,它是一樣的。後者只是爲你創建隊列,並始終與他們保持聯繫。

相關問題