2016-11-16 55 views
3

核心數據,自動更新導致問題的已更改對象,並使事情變得比需要的更混亂。如何製作核心數據對象的副本,保持不變

說我有這段代碼:

let fetchRequest = Track.fetchRequest() 

//update it 
do { 
    let tracksFound = try self.managedObjectContext.fetch(fetchRequest) as! [Track] 
    print("retrieved") 

    let trackToUpdate = tracksFound[0] 

    trackToUpdate.locality = "please dont have updated" 

    do { 
     try self.managedObjectContext.save() 
     print("saved") 
    } 
    catch { 
     fatalCoreDataError(error) 
    } 

    for t in tracksFound { 
     print(t.locality) 
    } 
} 
catch { 
    fatalCoreDataError(error) 
} 

你可以看到它取一個[Track]對象數組,然後將其更新的第一要素適當localityplease dont have updated。然後它保存這個對象。最後它讀取在開始時定義的tracksFound數組。我曾預期tracksFound保持不變,對象tracksFound[0].locality已更改爲please dont have updated

如何阻止核心數據更新我的對象?我基本上想要製作一個tracksFound的副本,它將保持不變,所以我可以稍後將它用於決策。

感謝

+0

簡單如果你沒有調用save()方法的意思,你的對象將不會變化。 –

+0

代碼'let trackToUpdate = tracksFound [0]'獲取*引用*到該元素,而不是副本。因此,當你改變'trackToUpdate'時,你實際上正在改變'tracksFound [0]'。 – Michael

+0

@Karthick不,在這旁邊很危險。 –

回答

2

正如邁克爾的評論中提到,trackToUpdate是的NSManagedObject實例的引用。指向同一對象的不同引用,...指向相同的對象。所以沒有辦法改變一個物體而不改變另一個物體,因爲沒有其他物體。 Swift通過意圖混淆了引用,誰擁有那真的,真正高明的想法。

正如你所說,你必須創建一個副本。 NSManagedObject沒有實現NSCopying協議。有很好的理由:如果實例引用其他實例(關係),則必須決定是否複製它們。這樣做會導致複製整個圖形的危險。如果不這樣做,可以讓你回到原來的問題,你分享一個被引用的實例。你必須做出決定。

將屬性複製到簡單字典中可能會更好。請記住,創建一個新的實例,這成爲對象圖的一部分。這是一種代碼味道(即使術語可能太難了),也不會有「短時間」的管理對象。

但是,您可以創建一個新實例。然後通過-entity獲得對象的實體描述。實體說明有一個屬性-properties,其中包含所有屬性的列表。使用這個,你可以迭代源屬性並將其存儲到新實例中。由於Objective-C的鍵值編碼,在運行時可以做到這一點。

+0

感謝您解釋這一點! – toast