[英]NSUserDefaults and Conditional Encoding of Custom Objects in an NSArray
我知道有很多關於如何在NSArray或NSMutableArray中歸檔自定義對象並將其保存在NSUserDefaults中的問題。 符合NSCoding協議並保存到NSUserDefaults沒問題,我在很多情況下都使用NSUserDefaults將用戶提交的數據存儲在我的應用程序中-它主要包含代表Person的對象(我們將其稱為NSObject子類“ Person”),在NSMutableArray中存儲了NSObject子類“ Property”的多個對象。 因此,數據結構如下所示:
NSMutableArray "persons":
Person "aPerson":
NSMutableArray "properties":
Property "aProperty"
Property "anotherProperty"
Person "anotherPerson:
...
最初,存檔和恢復信息沒有問題,因為Person和Property都符合NSCoding協議-但現在發生了一個問題,盡管最近幾天有成千上萬的google請求,但我仍然無法解決;)
一些Property對象包含對其他Person的引用(“參與者”,它們鏈接到相同的屬性,並且包含在NSMutableArray中)。 當我使用NSKeyedArchiver將整個數據存儲到NSUserDefaults時,我使用
[aCoder encodeObject:participants forKey:@"participants"];
在屬性的“ encodeWithCoder”方法中,可以將存儲對其他Person對象的引用的NSMutableArray“參與者”存檔。 但是,當我解碼這些Person對象時,它們是新創建的,並且與其他地方已經存在的Person對象分開。 NSMutableArray“參與者”僅包含引用 ,指向Person對象的弱鏈接,因此應該有條件地對其內容進行編碼 ,就像可以在“ encodeWithCoder”中手動處理其他對象一樣:
[aCoder encodeConditionalObject:anObject forKey:aKey];
當NSMutableArray被解碼時,它應該代表對已經存在的Person對象的引用列表-而不是全新的對象! 測試“ aPerson == [[aDecoder encodingObjectForKey:@“參與者”] objectAtIndex:0]”當前返回NO,盡管它在進行編碼/解碼過程之前返回了YES。
我希望我的解釋是可以理解的,並且您可以幫助我解決我的問題:)簡單來說:如何對NSMutableArray中包含的自定義對象進行條件編碼?
謝謝 !
如果NSMutableArray
對它包含的對象使用encodeConditionalObject:forKey:
則意味着如果這些對象不是在對象圖中的其他地方無條件地編碼的,則根本不會被編碼。 在這種情況下,這將無濟於事(該數組將為空)。
問題是您無法真正編碼對內存中對象的引用。 對象引用基本上只是指向內存中地址的指針。 下次啟動應用程序並創建相同的對象時(無論是通過取消存檔還是其他方式),幾乎肯定會在內存中具有不同的地址。 取消存檔程序無法“神奇地”知道哪個現有對象與其已存檔的引用相對應,因為當您退出應用程序時,內存地址(對象的“身份”)會失去所有含義。
您必須使用其他方法來標識您的對象,例如數據庫行ID,字典鍵等,並手動建立已歸檔鍵和與該鍵對應的現有對象的連接。
我也有這個問題。 我的對象具有與其他對象的一系列弱鏈接。 我知道鏈接到的所有對象都會被編碼,因此我只想確保可以重建鏈接。
使用單個弱鏈接可以使用:
aCoder.encodeConditionalObject(thing, forKey: "Thing")
...並且如果該商品已從其他位置進行編碼,則將使用對該編碼商品的引用。
但是,如果您有一個充滿“條件”項的數組,而該數組需要無條件編碼,該怎么辦?
我最后包裝了要鏈接的項目。
class thingLink: NSObject, NSCoding
{
weak var thing: Thing?
init(_ thing: Thing) {
self.thing = thing
}
required init?(coder aDecoder: NSCoder) {
thing = aDecoder.decodeObject(forKey: "Thing") as? Thing
}
func encode(with aCoder: NSCoder) {
// We encode these conditionally as they must be used elsewhere
aCoder.encodeConditionalObject(thing, forKey: "Thing")
}
}
...然后將它們存儲在我通常編碼的數組中。
aCoder.encode(things, forKey: "Things")
如果我移到數據庫來存儲內容,我認為這也將有所幫助,因為我需要一個單獨的表來存儲鏈接並保持優先級等。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.