3

我在CoreData和Parent-Child MOC中遇到此問題:將對象添加到子MOC時,保存它們並保存父MOC所有對象都將其屬性重置爲默認值。父MOC獲取來自兒童MOC的空數據的更改

我在這裏粘貼了兩個MOC的日誌,特別是這些日誌中的「stringAttribute」和「date」屬性被重置。

我到處搜索這個問題,但我沒有找到任何東西,我也看了很多親子MOC的實現,但我無法弄清楚我做錯了什麼。

在此先感謝!

下面的代碼片段:

我一些NSManagedObject添加到主背景,然後用saveContext:方法

// Another singleton method 
- (void)anotherMethod 
{ 
    [...] 
    [self.managedObjectContext insertObject:managedObject]; 
    NSError *error; 
    save = [self saveContext:&error]; 
    [...] 
} 

// Database manager singleton method 

- (BOOL)saveContext:(DKError *__autoreleasing *)error 
{ 

    __block BOOL save = NO; 
    __block NSError *internalError; 

    [self.managedObjectContext performBlockAndWait:^{ 
     internalError = nil; 

     [self.managedObjectContext log]; // See log 1.1 below 

     save = [self.managedObjectContext save:&internalError]; 
     if (!save) { 
      NSLog(@"Error saving data in main context"); 
     } else { 

      [self.managedObjectContext.parentContext performBlock:^{ 
       internalError = nil; 
       save = NO; 

       [self.managedObjectContext.parentContext log]; // See log 1.2 below 

       save = [self.managedObjectContext.parentContext save:&internalError]; 
       if (!save) { 
        NSLog(@"Error saving data to disk!"); 
       } 
      }]; 

     } 
    }]; 
    *error = [DKError errorWithNSError:internalError]; // Custom error class 
    return save; 
} 

父救 - 兒童上下文代碼

- (NSManagedObjectContext *)writerObjectContext 
{ 
    if (_writerObjectContext != nil) 
     return _writerObjectContext; 

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
    if (coordinator != nil) { 
     _writerObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
     [_writerObjectContext setPersistentStoreCoordinator:coordinator]; 
    } 
    return _writerObjectContext; 
} 

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

    _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 
    [_managedObjectContext setParentContext:[self writerObjectContext]]; 

    return _managedObjectContext; 
} 

日誌1.1

Inserted objects: 
{(
    <Entity: 0x9595120> (entity: Entity; id: 0x9582d40 <x-coredata:///Entity/t24D0F98B-CB94-41D3-BEDD-79913454A9152> ; data: { 
    [...] 
    dateAttribute = "2013-07-12 10:36:31 +0000"; 
    stringAttribute = ricercaEntity; 
    [...] 
}) 
)} 

日誌1.2

Inserted objects: 
{(
    <Entity: 0xb53ce80> (entity: Entity; id: 0x9582d40 <x-coredata:///Entity/t24D0F98B-CB94-41D3-BEDD-79913454A9152> ; data: { 
    [...] 
    dateAttribute = "2013-01-05 11:00:00 +0000"; 
    stringAttribute = nil; 
    [...] 
}) 
)} 

UPDATE

我已經應該提到的是,managedObject加入上下文通過上下文初始化。然後在致電saveContext:之前,我檢查是否存在object.managedObjectContext,如果沒有,那麼我將其設置爲[self managedObjectContext],即使用上述方法創建的那個。因此,要麼如果managedObject與零上下文創建,創建的或具有:

+ (id)newObjectForInsertion 
{ 
    return [[self alloc] initWithEntity:[self entityDescription] insertIntoManagedObjectContext:[DKDatabaseManager defaultManager].managedObjectContext]; 
} 

相關managedObjectContext是在同一個隊列(NSMainQueueConcurrencyType)。

否則,如果managedObject+newObjectForInsertion所有saveContext:併發鏈回報是,所有的變化都傳遞給父上下文的創建。

我不知道它是一個錯誤還是CoreData應該工作的方式。

蘋果開發者論壇

同樣的問題:

https://devforums.apple.com/thread/174677?tstart=90

+0

你確定它是日誌中的同一個實體嗎? dateAttribute不重置,但完全不同。 – eofster

+0

是的。它應該是相同的,因爲傳遞的id是相同的('entity:Entity; id:0x9582d40')。 date屬性重置爲.xcdatamodeld中設置的默認值。應該使用'performBlockAndWait:'安全地傳遞更改,所以我不認爲是objectID的問題。我沒有完全確定BTW – Pencildrummer

回答

1

你應該初始化背景與concurrencyType:

context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 

此外,設置合併政策

[context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy]; 

NSMergeByPropertyObjectTrumpMergePolicy

這一政策合併衝突的持久性存儲的版本的 的對象和當前內存版本之間,以 內存的變化給予優先考慮。合併由個人財產發生。對於在外部源和 內存中已更改的 屬性,內存中的更改將衝擊外部內存。

順便說一句,我發現類似的問題:strange-behavior-when-using-child-parent-nsmanagedobjectcontext看看接受的答案,它使用通知合併。

+0

正如你所看到的,這兩個上下文都是帶有concurrencyType的init,一個是帶'NSPrivateQueueConcurrencyType'的寫入者,另一個帶有'NSMainQueueConcurrencyType'。我只是試圖在作家上下文中設置合併策略,但沒有任何改變。我查看鏈接,但一個解決方案做同樣的事情(設置背景爲父),另一個解決方案使用'NSManagedObjectContextDidSaveNotification',我的理解應該使用'old-before-5.0'父子模式。 – Pencildrummer