簡體   English   中英

核心數據不會持續對數據庫的屬性更新

[英]Core Data Wont Persist Property Updates to Database

我正在使用NSManagedObject的子類。 實際上,它繼承自一個繼承自NSManagedObject的類的類(這應該不是問題,對嗎?)。

問題

在對對象的屬性進行更改后,對象會記住其生命周期的更改,但更改永遠不會保存到數據庫中。

我怎么知道這個?

我知道這是因為:

  • 當我重新啟動應用程序時,我所做的更改將丟失。
  • 告訴上下文刷新對象 - 在我對對象進行了更改並告訴上下文保存之后 - 在我進行更改之前將對象的值設置回原始狀態。
  • 在模擬器中運行應用程序時,我可以查看Finder中的sqlite數據庫文件,當我嘗試保存上下文時,它的修改日期不會更新。

沒有任何東西寫入數據庫!

上下文

我正在使用自動生成的委托方法來創建商店協調器和上下文。 然后我按照文檔中的建議將上下文傳遞給它們的init方法中的視圖控制器。 這家商店是SQLite。

我能夠成功地將對象插入數據庫並讀取它們。 我甚至可以對新插入的對象進行屬性更改並成功保存。 當對象被拉回數據庫時,我似乎無法更新對象屬性。

通過來自另一個對象的關系從商店中獲取對象。 在更改其屬性后,我調用上下文的save方法。 但是,在這樣做之前,我調用對象的isUpdated方法和上下文的hasChanges方法,並且都返回false。 它們不應該返回true,因為我剛剛更改了對象的屬性但沒有保存上下文嗎?

更多

如果我在保存上下文之前調用對象的committedChanges方法,但是,傳入我已更改的屬性的名稱,我會返回屬性的正確值。 我不確定這意味着什么。 我原以為這意味着對象的新屬性值已成功保存,但很明顯它們沒有保存。

我知道結果對象是在上下文中注冊的。 如果我打電話

[[result managedObjectContext] refreshObject:result mergeChanges:YES];

對象恢復為原始屬性值。 這意味着上下文存在,並且它是從中獲取記錄的相同上下文。 這意味着新屬性值永遠不會寫入數據庫。

一些代碼

這是我正在探討所有這些事情的代碼。 我的代碼中有其他地方我正在進行屬性更改,但更改永遠不會保存。

- (IBAction)statusControlChanged:(UISegmentedControl *)control {
WCAAssessmentResult *result = [self currentResult];

    /* printing the existing property values */
    if (![result.complete boolValue]) NSLog(@"result is in progress!");
    else if ([result.passed boolValue]) NSLog(@"result is passed!");
    else NSLog(@"result is not passed!");

    /* changing the property values */
    switch (control.selectedSegmentIndex) {
        case 0:
            NSLog(@"setting incomplete");
            result.complete = [NSNumber numberWithBool:NO];
            break;
        case 1:
            NSLog(@"setting passed");
            result.passed = [NSNumber numberWithBool:YES];
            result.complete = [NSNumber numberWithBool:YES];
            break;
        case 2:
            NSLog(@"setting failed");
            result.passed = [NSNumber numberWithBool:NO];
            result.complete = [NSNumber numberWithBool:YES];
            break;
        default:
            break;
    }

    /* this method always returns an empty dictionary */
    NSLog(@"%@", [result changedValues]);

    /* this method returns the values that I just set */
    NSLog(@"%@", [result committedValuesForKeys:[NSArray arrayWithObjects:@"complete", @"passed", nil]]);

    /* isUpdated returns false */
    if (![result isUpdated]) {
        NSLog(@"result is not updated?! WTF!?!?");
    }

    /* hasChanges returns false */
    if (![[result managedObjectContext] hasChanges]) {
        NSLog(@"context has no changes!? WTF!?!?");
    }

    /* saving the context produces no error */
    NSError *error = nil;
    if (![[result managedObjectContext] save:&error]) {
        NSLog(@"save failed");
        NSLog(@"%@",[error description]);
    }
}

扭曲

如果我通過在上下文中插入新記錄來創建新的結果對象,我可以設置該對象的屬性並成功保存。 在上面的代碼中,我將對象作為來自另一個對象的多對象關聯的成員。 這是一個線索嗎?

我正在撕裂我的頭發。 這到底怎么可能出錯?

什么不是問題

  • 我已經記錄了對象的類,它確實是正確的類
  • 我確保我保存的managedObjectContext與對象的上下文相同
  • 我沒有對托管對象類的自動生成的setter / getter方法進行任何更改
  • 我嘗試過使用setValue:forKey:方法而不是對象的屬性
  • 我使用-com.apple.CoreData.SQLDebug 1參數來記錄Core Data SQL,當我更新並保存對象的屬性時沒有記錄SQL

我真的不明白你的陳述

WCAAssessmentResult *result = [self currentResult];

實際上,如果要從對象訪問多對多關系,則應該返回一個集合,而不是對象。 無論如何,沒有看到代碼,很難說。 您遇到的問題可能存在,也可能不存在。

我寧願在你的代碼中期望類似下面的代碼片段來訪問屬於多對多關系的對象。 我假設yourObject是用於訪問to-many關系中WCAAssessmentResult對象的對象,我將其稱為results

NSMutableSet *resultObjects = [yourObject mutableSetValueForKey:@"results"];
NSPredicate *predicate = ...
[resultObjects filterUsingPredicate:predicate];

for(WCAAssessmentResult *result in resultObjects){

   // modify as needed the current result object

}

NSError *error = nil;
if (![managedObjectContext save:&error]) {
        NSLog(@"save failed");
        NSLog(@"%@",[error description]);
}

您是否驗證了用於保存對象的managedObjectContext是否有效(不是nil)?

一些想法沒有特別的順序:

我會記錄result對象的類,並確保它是您認為的類。 與超級/子類的某些混淆可能導致某些值未被保存。

如果您對層次結構中的任何類中的setter / getter方法進行了任何更改,請仔細查看這些方法,尤其是在使用primativeValue方法時。 簡單地省略willChangeValuedidChangeValue會導致更改對上下文不可見,有時也會對對象本身不可見。

我會記錄您正在保存的上下文以及result對象的managedObjectContext屬性。 確認它們確實是相同的背景。

使用屬性訪問器(點表示法)跳過並使用setValue:forKey ,看看是否有任何區別。 如果是這樣,您有一個訪問者問題。 同樣,您可以嘗試使用setPrimativeValue:forKey來檢查訪問器問題。

如果我不得不下注,我會把錢花在你將fetch返回的對象分配給錯誤的類上。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM