2010-12-17 87 views
7

alt text使用多線程核心數據應用程序設計的幫助

上面是對我的模型的簡化。我的應用程序有一個NSWindowController對象控制用戶帳戶實體的兩個NSViewController對象。當用戶登錄到應用程序時,他們可以通過調出相關的視圖控制器來修改用戶或帳戶信息。在後臺,我有應用程序定期將用戶的日誌填充到單獨線程上的應用程序委託中。

我使用單獨的NSManagedObjectContext作爲後臺線程和應用程序委託的NSManagedObjectContext用於視圖控制器中的數據輸入。我想知道幾件事情:

1)這是一個很好的做法嗎?我應該爲每個視圖控制器創建一個NSManagedObjectContext,然後在用戶完成更改時合併上下文嗎?

2)因爲log實體是在後臺線程中創建的,所以它有它自己的NSManagedObjectContext。但是,每個日誌包括來自用戶帳戶實體的信息,這些信息是在應用程序代理的NSManagedObjectContext中創建的。這是怎麼了獲取用戶:

- (NSManagedObjectID*) fetchUser:(NSString*) userID { 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"user":inManagedObjectContext:self.managedObjectContext]; 
    /** snip **/ 
} 

此方法由後臺線程調用如下:

NSManagedObjectID* userObjectID = [self fetchUser:userID]; 
NSManagedObject* userObject = [self.logsManagedObjectContext objectWithID:userObjectID]; 

是我在fetchUser線程安全的我在做什麼?如果其中一個視圖正在修改同一用戶,那麼在獲取用戶時是否需要鎖定主管理對象上下文?從this article我瞭解(也許不正確),我可能必須這樣做。到目前爲止,我沒有遇到任何問題,但我不想留下潛在的優勢案例。

3)當視圖控制器之一,使更改應用程序委託的NSManagedObjectContext其職位,被處理的通知如下:

- (void)contextDidSave:(NSNotification *)notification { 
    SEL selector = @selector(mergeChangesFromContextDidSaveNotification:); 
    [self.logManagedObectContext performSelector:selector onThread:backgroundThread withObject:notification waitUntilDone:NO]; 
} 

這是我應該如何處理合並或者我應該合併應用程序代理的NSManagedObjectContext而不是?我發現這樣做(在主線程上)鎖定了用戶界面。

任何幫助將不勝感激。

回答

9

NSManagedObjectContext對象不是線程安全的。這意味着如果您希望從多個線程訪問Core Data,則每個線程都需要一個線程(並且也在該線程上創建)。其中每個可以使用相同的NSPersistentStoreCoordinator,這將串行化訪問持久性存儲。

這是因爲每個NSManagedObjectContext知道如何正確地鎖定NSPersistentStoreCoordinator當它在使用中,避免碰撞。遵循這些規則,您應該保持線程安全。

正如您已經在做的那樣,應該使用NSManagedObjectID對象將Core Data對象從一個MOC傳遞到另一個(以及從一個線程到另一個線程的擴展)。但是,您正在調用fetchUser:,它使用主線程中的MOC,在後臺使用。這是不正確的。必須從主線程調用fetchUser:方法調用。當然,沒有什麼可以阻止你使用後臺MOC在後臺線程中檢索用戶。

總之,總是從它在創建線程的NSManagedObjectContext電話。

這裏的關鍵是要確保兩個MOCS知道對方的保存,所以你必須註冊才能收到通知每個環境。然後您應該從MOC的相應線程執行mergeChangesFromContextDidSaveNotification:。目前,您的後臺上下文會被通知主線程上下文的變化,但反之亦然。

哦,並且沒有必要爲每個NSViewController有一個單獨的上下文。作爲UI元素,它們與上下文的交互將發生在同一個(主)線程上,因此共享沒有問題。

+0

我不知道我可以從後臺MOC中檢索用戶。我需要做的就是給他們相同的** NSPersistentStoreCoordinator **?如果我這樣做,我需要檢索使用對象ID或我可以直接獲取對象? – David 2010-12-23 23:33:25

+0

您可以直接獲取對象。只要確保編寫代碼以合併來自共享相同協調器的其他MOC的通知時的更改。 – paulbailey 2010-12-30 11:04:10