2012-05-01 69 views
1
我有在後臺線程GCD核心數據的問題

...我想更新記錄,但它獲取和設置值後,似乎並沒有真正保存更新記錄。核心數據後臺線程不能更新記錄

isUpdate是一個布爾我有安裝程序告訴我,我是否正在運行第一次解析/保存或者它是否是我需要更新的記錄。在我的情況下,當我更新記錄時,它實際上並未在我的商店中更新。

我使用MagicalRecord幫手。這裏是我的代碼:

// Create background context 
NSManagedObjectContext *backgroundContext = [[NSManagedObjectContext alloc] init]; 
[backgroundContext setPersistentStoreCoordinator:[NSPersistentStoreCoordinator defaultStoreCoordinator]]; 
// Save the background context and handle the save notification 
[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(backgroundContextDidSave:) 
              name:NSManagedObjectContextDidSaveNotification 
              object:backgroundContext]; 

// Parsing data... 
//.. 

Record *record; 
if (!isUpdate) { 
    record = [NSEntityDescription insertNewObjectForEntityForName:@"Record" inManagedObjectContext:backgroundContext]; 
} else { 
    NSPredicate *recordPredicate = [NSPredicate predicateWithFormat:@"SELF.tag == %@", [[node attributeForName:@"tag"] stringValue]]; 
    record = [Record findFirstWithPredicate:recordPredicate]; 
} 
[record setTitle:[[recordNode attributeForName:@"title"] stringValue]]; 

// Parsing other data... 
//.. 

NSError *error = nil; 
// save the context 
[backgroundContext save:&error]; 
if (error) { 
    NSLog(@"An error occurred: %@", error); 
} 

而這裏的通知:

- (void)backgroundContextDidSave:(NSNotification *)notification { 
    // Make sure we're on the main thread when updating the main context 
    if (![NSThread isMainThread]) { 
     [self performSelectorOnMainThread:@selector(backgroundContextDidSave:) 
          withObject:notification 
         waitUntilDone:NO]; 
     return; 
    } 
    // merge in the changes to the main context on the main thread 
    [[NSManagedObjectContext defaultContext] mergeChangesFromContextDidSaveNotification:notification]; 
} 
+0

您是否設置了斷點,首先在isUpdate的if/else檢查中查看哪個被調用;然後在通知處理程序中?你有沒有檢查mergeChangesFromContext ...被調用,或者它不是? –

+0

是的,兩者都被正確調用。 – runmad

回答

1

您正在混合兩個上下文。此代碼可能是不好的:

record = [Record findFirstWithPredicate:recordPredicate]; 

我假設這會在不同的上下文中找到記錄,而不是您的backgroundContext。您應該將其更改爲如下所示:

record = [Record findFirstWithPredicate:recordPredicate inManagedObjectContext:backgroundContext]; 
+1

謝謝,我之前嘗試過,但我得到這個錯誤:終止應用程序由於未捕獲的異常'NSInvalidArgumentException',原因:'只能使用-performBlockAndWait:在用隊列創建的NSManagedObjectContext。'我創建隊列中的背景上下文。有任何想法嗎? – runmad

+0

順便說一下,這個錯誤來自於MagicalRecord'+(NSArray *)MR_executeFetchRequest:(NSFetchRequest *)request inContext:(NSManagedObjectContext *)context' – runmad

+0

另一個更新:我不得不使用MR輔助方法'[NSManagedObjectContext contextForCurrentThread]'但是如果我更新XML並解析它,我仍然看不到數據的任何更改。 – runmad

2

您的代碼聽起來很奇怪,我。

你爲什麼要註冊在後臺線程NSManagedObjectContextDidSaveNotification通知?也許我錯了,但是您需要在應用程序的其他位置註冊該通知。

如果你想它的工作原理,你可以在主線程中註冊該通知。例如,您可以在AppDelegate中執行此操作。

例如在didFinishLaunchingWithOptions:方法,你CAND做

[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(backgroundContextDidSave:) 
              name:NSManagedObjectContextDidSaveNotification 
              object:backgroundContext]; 

然後,總是AppDelegate內,您可以合併使用你寫的方法的變化:

- (void)backgroundContextDidSave:(NSNotification *)notification { 
    // Make sure we're on the main thread when updating the main context 
    if (![NSThread isMainThread]) { 
     [self performSelectorOnMainThread:@selector(backgroundContextDidSave:) 
          withObject:notification 
         waitUntilDone:YES]; 
     return; 
    } 
    // merge in the changes to the main context on the main thread 
    [[NSManagedObjectContext defaultContext] mergeChangesFromContextDidSaveNotification:notification]; 
} 

代碼執行下列步驟操作:

  1. 首先檢查您是在主線程中運行還是在主線程中運行或不。
  2. 既然你註冊的通知可以從一個線程 從主要的一個起源不同,你需要將 主線程上執行選擇。
  3. 最後執行與包含您在後臺進行的 變動通知的合併。

完成後,您可以看到主要上下文已更新,其中更改了主要上下文。

編輯

也許你可以試試也改變waitUntilDone爲YES。

希望它有幫助。

+0

我不認爲你的答案是誠實的,這部分代碼有什麼問題。初始解析插入新對象的工作非常好,它是提取記錄然後更新每個不起作用的記錄。 – runmad

+0

@runmad我添加了一個編輯。乾杯。 –