2013-05-10 60 views
2

我有一個雙重託管對象上下文設置,我有一個父/子MOC關係。父級負責直接寫入專用隊列中的數據庫(NSPrivateQueueConcurrencyType),然後我有一個負責爲主線程(NSMainQueueConcurrencyType)提取和保存數據的子上下文。託管對象上下文不合並來自後臺上下文的變更

上下文的工作方式與我在更改主隊列上下文並保存時一樣,然後將更改合併到後臺隊列上下文並在後臺線程上寫入數據庫。

我遇到的問題是當我直接將數據寫入背景隊列上下文,然後嘗試將它合併到主隊列上下文。這些對象在商店中正確存儲,並且當我合併這些更改時似乎可行。但是,如果我試圖在將數據保存到存儲後直接對主隊列上下文創建NSFetchRequest,那麼數據是陳舊的,而不是正確的更新數據。

下面是代碼摘錄,應該幫助您瞭解我在做什麼。有些需要注意的是從JSON工作中正確返回NSManagedObjects的邏輯。此外,我已經測試並且在UI嘗試對主隊列MOC發出任何提取請求之前運行mergeChangesFromContextDidSaveNotification。你們都有什麼想法發生了什麼?

// Context Setup 
- (NSManagedObjectContext *)backgroundWriterManagedObjectContext 
{ 
    if (_backgroundWriterManagedObjectContext != nil) 
     return _backgroundWriterManagedObjectContext; 

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
    if (coordinator != nil) 
    { 
     _backgroundWriterManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
     _backgroundWriterManagedObjectContext.persistentStoreCoordinator = coordinator; 
     _backgroundWriterManagedObjectContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy; 
     _backgroundWriterManagedObjectContext.undoManager = nil; 
    } 
    return _backgroundWriterManagedObjectContext; 
} 

- (NSManagedObjectContext *)managedObjectContext 
{ 
    if (_managedObjectContext != nil) 
     return _managedObjectContext; 

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
    if (coordinator != nil) 
    { 
     _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 
     _managedObjectContext.parentContext = _backgroundWriterManagedObjectContext; 
     _managedObjectContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy; 
     _managedObjectContext.stalenessInterval = 0.0; 
    } 
    return _managedObjectContext; 
} 

// save MOC 
- (void)saveManagedObjectContext 
{ 
    @try 
    { 
     // perform synchronous process to save to the main MOC 
     [_managedObjectContext performBlockAndWait:^(void) 
     { 
      __block NSError *error = nil; 

      // push any changes in the main context to the background writer context 
      if (![_managedObjectContext tryLock]) 
       [VS_Log VS_LogError:[NSString stringWithFormat:@"VS_CoreDataManger - Unable To Lock Managed Object Context: %@", error.localizedDescription]]; 

      if (![_managedObjectContext save:&error]) 
       [VS_Log VS_LogError:[NSString stringWithFormat:@"VS_CoreDataManger - Error Saving Managed Object Context: %@", error.localizedDescription]]; 

      [_managedObjectContext unlock]; 

      // save the background writer context 
      [_backgroundWriterManagedObjectContext performBlock:^(void) 
      { 
       error = nil; 

       if (![_backgroundWriterManagedObjectContext tryLock]) 
        [VS_Log VS_LogError:[NSString stringWithFormat:@"VS_CoreDataManger - Unable To Lock Background Writer Managed Object Context: %@", error.localizedDescription]]; 

       if (![_backgroundWriterManagedObjectContext save:&error]) 
        [VS_Log VS_LogError:[NSString stringWithFormat:@"VS_CoreDataManger - Error Saving Background Writer Managed Object Context: %@", error.localizedDescription]]; 

       [_backgroundWriterManagedObjectContext unlock]; 
      }]; 
     }]; 
    } 
    @catch (NSException *exception) 
    { 
     [VS_Log VS_LogException:exception]; 
    } 
} 

// This code runs when attempting to save objects from a web service call 
[_backgroundWriterManagedObjectContext performBlock:^(void) 
    { 
     // create a new process object and add it to the dictionary 
     __block VS_CoreDataRequest *request = [[VS_CoreDataRequest alloc] init]; 

     // .. LOGIC HERE DESERIALIZES THE JSON AND RETURNS AN ARRAY OF NSMANAGEDOBJECTS 

     // perform synchronous process to save to the main MOC 
     @try 
     { 
      NSError *error = nil; 

      [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeChangesFromContextDidSaveNotification:) name:NSManagedObjectContextDidSaveNotification object:_backgroundWriterManagedObjectContext]; 

      if (![_backgroundWriterManagedObjectContext tryLock]) 
       [VS_Log VS_LogError:[NSString stringWithFormat:@"VS_CoreDataManger - Unable To Lock Background Writer Managed Object Context: %@", error.localizedDescription]]; 

      if (![_backgroundWriterManagedObjectContext save:&error]) 
       [VS_Log VS_LogError:[NSString stringWithFormat:@"VS_CoreDataManger - Error Saving Background Writer Managed Object Context: %@", error.localizedDescription]]; 

      [_backgroundWriterManagedObjectContext unlock]; 

      // submit changes back to the forground context 
      [_managedObjectContext performBlock:^(void) 
      { 
       NSMutableArray *objects = [[NSMutableArray alloc] init]; 

       // iterate through the updated objects and find them in the main thread MOC 
       for (VS_BaseManagedObject *object in request.objects) 
       { 
        // get the object from the main managed object context 
        NSError *error; 
        NSManagedObject *obj = [_managedObjectContext existingObjectWithID:object.objectID error:&error]; 

        if (error) 
         [VS_Log VS_LogError:[NSString stringWithFormat:@"VS_CoreDataManager - Error: %@", error.localizedDescription]]; 

        if (obj) 
        { 
         [_managedObjectContext refreshObject:obj mergeChanges:YES]; 
         [objects addObject:obj]; 
        } 
       } 

       // RETURN FROM METHOD SO UI CAN REGAIN CONTROL 
      }]; 
     } 
     @catch (NSException *exception) 
     { 
      [VS_Log VS_LogException:exception]; 
      return; 
     } 
    }]; 

// Merges changes from parent to child context 
- (void)mergeChangesFromContextDidSaveNotification:(NSNotification *)notification 
{ 
    // remove observer 
    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:_backgroundWriterManagedObjectContext]; 

    // merge the changes 
    [_managedObjectContext mergeChangesFromContextDidSaveNotification:notification]; 
} 
+0

由於您的代碼和概念看起來不錯,所以您提供的信息中沒有任何意義。您是否使用FRC將數據提供給視圖?如果是這樣,我懷疑它與你的FRC有更多關係。我不確定獨立訪存是否會按照您的要求更新MOC。我會研究一下。 – andrewbuilder 2016-03-01 00:28:15

回答

0

您沒有調用進程掛起的更改。

相關問題