我正在使用核心數據的多線程應用程序。具有諷刺意味的是,當我得知Core Data不是線程安全的時候,我認爲應用程序已經接近完成了......因此,我現在添加了多上下文,而不是從Xcode模板獲得的單一上下文到目前爲止,工作到目前爲止,真的,但這是比我猜想的技巧運氣更好)合併到父/主上下文後,子上下文對象變爲空
我試圖使用>的iOS 5.0的方法與父/子上下文,這將適合我想要做什麼,但當我在子上下文中插入有效數據/屬性的有效對象時,它們在父上下文中全部變爲零或0(取決於屬性類型)。
我注意到,有類似的帖子,但沒有任何答案;
Parent MOC get changes with empty data from child MOC
下面是一些代碼來獲取的想法;
我有一個單獨的管理器,用戶界面用來「做東西」,然後在任務完成時使用委託或回調。反過來這位經理有一個模型,經理來處理持久性數據管理,以及其他一些通訊經理交談的網絡/ REST的API等
- (void) doSomeStuff:(NSString*)someParam
callbackObject:(NSObject*)object
onSuccess:(SEL)successSelector
onFailure:(SEL)failureSelector
{
//Kick as an async thread since we don't want to disturb the UI
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void)
{
//Ask model manager for a nice context to work with...
//NOTE; All contexts (private ones) are stored in a NSDictionary using currentThread as key, so that we always can access the "correct" context at anytime if we need to insert/delete/change anything in the context
NSManagedObjectContext* privateContext = [self.modelManager getManagedObjectContext];
//Perform stuff in block since our context is of NSPrivateQueueConcurrencyType
[privateContext performBlockAndWait:^{
//... do the actual stuff, go online, talk to a REST-API, wait for things, which will eventually result in a new object being created
User* user = ...;
//Store object in model manger which is my abstraction of CoreData
//NOTE: the modelManager will get a reference to the currently used privateContext and use it to insert the object
[self.modelManager addUser:user];
//Save model!
[self.modelManager save];
}];
//Trigger callback, if applicable
if (loggedInUserGuid && successSelector)
{
[object performSelectorOnMainThread:successSelector withObject:loggedInUserGuid waitUntilDone:NO];
}
});
}
中的ModelManager保存功能考慮到上下文併發性類型,並且在使用子/父上下文時將按照規範行事;
- (void) save
{
//Get current context...
NSManagedObjectContext* currentContext = [self getManagedObjectContext];
//If the current context has any changes...
if ([currentContext hasChanges])
{
//Changes detected! What kind of context is this?
switch (currentContext.concurrencyType)
{
case NSPrivateQueueConcurrencyType:
{
NSError* error = nil;
if (![currentContext save:&error])
abort();
if (self.mainManagedObjectContext hasChanges])
{
[self.mainManagedObjectContext performBlockAndWait:^{
NSError *mainError;
if (![self.mainManagedObjectContext save:&mainError])
abort();
}];
}
break;
}
....
}
}
}
通過之前和搶救孩子的情況和家長/主上下文之後加入調試輸出,我注意到,插入的對象是有很好的孩子而言,和孩子方面說「hasChanges == YES 「,而正如預期的那樣,主要上下文表示」hasChanges == NO「。
(entity: User; id: 0x10c06c8c0 <x-coredata:///User/tDFBBE194-44F9-44EC-B960-3E8E5374463318> ; data: {
created = nil;
emailAddress = "[email protected]";
firstName = Wilton;
guid = "2eaa77fa-0d2c-41b8-b965-c4dced6eb54a";
lastName = Millfjord;
nbrOfOfflineKeys = 5;
password = 123456;
})
主上下文後保存爲好,並期待它在保存前的registeredObjects,我們可以看到,「hasChanges == YES」(預期後,孩子的節約插入的對象/合併到它的父但是,另外 - 所有PARAMS和屬性現在爲零或0取決於屬性類型...;
(entity: User; id: 0x10c06c8c0 <x-coredata:///User/tDFBBE194-44F9-44EC-B960-3E8E5374463318> ; data: {
created = nil;
emailAddress = nil;
firstName = nil;
guid = nil;
lastName = nil;
nbrOfOfflineKeys = 0;
password = nil;
})
正如你所看到的,ID是一樣的,所以它的「相同」的對象,但沒有/重置內容我已經嘗試了所有「setMergePolicy」的各種組合,但沒有效果。我甚至嘗試過使用iOS 5.0方法添加一個NSNotificationCentre方法,其中我「mergeChangesFromContextDidSaveNotification」,並且唯一可以驗證的是NSNotification參數中的數據是有效的,並且是「好數據」,但主要上下文仍未正確更新。結果仍然是一個空洞的對象。
期待您的想法和想法。
/馬庫斯
更新
創建新的管理對象時,使用的主要方面,無論所使用的代碼線程/被當時正在執行上下文performBlock ...
NSEntityDescription *entity = [NSEntityDescription entityForName:@"User" inManagedObjectContext:self.mainManagedObjectContext];
User* user = (User *)[[User alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];
對象用戶其後懸掛沒有上下文,直到後來,當我決定將其添加到管理範圍內(使用我的getManagedObjectContext到GE適當/當前上下文)。
[[self getManagedObjectContext] insertObject:user];
您是否嘗試過使用performBlock:而不是performBlockAndWait?看着你的問題和你鏈接的其他兩個人,我唯一注意到的是你全部使用了performBlockAndWait。你有什麼理由想等待?我使用CoreData時遵循類似的模式,但我只使用performBlock。 – TheJer
我試圖改變執行塊,但沒有改變行爲。爲什麼我寧願performBlockAndWait是因爲我希望經理「doSomeStuff」做一些異步操作以避免干擾主線程。因此,我開始分派一個新的異步線程。一旦執行,該線程又會向modelManager請求私有上下文。因此,我認爲這足夠了異步進程,並且我們已經從主線程和UI干涉中分派出來,所以讓我們等待該塊結束。 –
不過,我想知道,如果我基本上在這裏嵌套主線程的事實可能會干擾?我的意思是,主線程調用doSomeStuff調度一個異步工作線程,該線程又調用performBlockAndWait ...?一個太多了?這種方法與ref-examples有所不同,因爲我根據正在運行的線程獲取/創建私有上下文......我已經明確地看到的大多數示例都創建了一個新的私有上下文,然後執行異步(從主線程執行)? 。只是在大聲思考......我也把「保存」機制作爲一個函數,而不是內嵌在塊內的代碼......? –