[英]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.