2011-11-18 59 views
2

假設我有一個名爲ItemNSManagedObject子類。每當保存item實例時,我想根據瞬態屬性的計算值更新屬性。我知道,只要瞬態屬性發生變化,我就可以更新屬性,但對於這個問題,假設我不想這樣做的一個很好的理由。如何在保存之前自動設置計算的NSManagedObject屬性?

我試圖做到這一點的方法willSave如下:

- (void)willSave 
{ 
    self.computedProperty = [self computedValueFromTransientProperty]; 
} 

保存上下文時,這會導致系統崩潰。如果我將代碼移出willSave並在調用save之前顯式設置該屬性,則它可以正常工作。蘋果文檔說你應該避免更改willSave中的託管對象屬性。

問題:是否有一種很好的方法可以將功能構建到NSManagedObject子類中,因此屬性可以在保存之前進行更新,無需從類的外部明確設置屬性,並且無需每次設置屬性瞬態屬性更改?

回答

7

您可以從willSave設置持久性屬性,您只需要更加小心。

willSave文檔:

這種方法可以有「副作用」關於持久值。例如,您可以使用 來計算來自其他瞬態或暫存器值的持久值。

如果要更新持久性屬性值,則在進行更改之前,通常應測試任何新值與現有值 是否相等。如果使用標準的 訪問器方法更改屬性值,Core Data將觀察由此產生的更改 通知,因此在保存對象的 託管對象上下文之前再次調用willSave。如果你繼續在willSave中修改一個值, willSave將繼續被調用,直到你的程序崩潰。

那麼,發生了什麼事是你改變computedProperty,這是造成willSave再次調用,從而改變其computedProperty再次呼籲willSave,直到你的程序崩潰。

要解決這個問題,你需要檢查是否computedProperty需要重新設置:

- (void)willSave 
{ 
    id computed = [self computedValueFromTransientProperty]; 
    if (![self.computedProperty isEqual:computed]) 
    { 
     self.computedProperty = computed; 
    } 
} 

這將意味着computedValueFromTransientProperty將調用兩次,所以你可能不希望這樣做,如果該方法是計算成本很高。

另一種選擇是使用原始設定的方法,這將意味着willSave將不會被調用兩次,但可能會會影響依賴於你的應用程序如何與核心數據交互:

- (void)willSave 
{ 
    self.primitiveComputedProperty = [self computedValueFromTransientProperty]; 
} 
+1

謝謝,我沒看到在文檔中,但沒有直接思考。我使用了你的第一個建議,但是爲了消除雙重計算,添加了一個初始化爲nil並在'didSave'中設置爲零的iVar。在'willSave'中,如果這個iVar是零,我將它設置爲計算值。然後我使用上面的邏輯將這個iVar與持久屬性進行比較。很好的工作,我只做一次昂貴的計算。謝謝! – XJones

相關問題