我知道有很多关于如何在NSArray或NSMutableArray中存档自定义对象并将它们保存在NSUserDefaults中的问题。符合NSCoding协议并保存到NSUserDefaults是没有问题的,我使用NSUserDefaults将很多用户提交的数据存储在我的应用程序中 - 它主要包含代表Person的对象(让我们调用NSObject子类“Person”)具有存储在NSMutableArray中的NSObject子类“Property”的多个对象。因此,数据结构如下所示:
NSMutableArray "persons":
Person "aPerson":
NSMutableArray "properties":
Property "aProperty"
Property "anotherProperty"
Person "anotherPerson:
...
归档和恢复信息起初并不成问题,因为人员和财产都符合NSCoding协议 - 但现在出现了一个问题,尽管过去几天有数千个谷歌请求,但我还是无法解决这个问题。 )
某些Property对象包含对其他人的引用(“Participants”,它们链接到同一属性并包含在NSMutableArray中)。 当我使用NSKeyedArchiver将整个数据存储到NSUserDefaults时,我使用
[aCoder encodeObject:participants forKey:@"participants"];
在Property的“encodeWithCoder”方法中归档NSMutableArray“参与者”,它存储对其他Person对象的引用。但是当我解码那些Person对象时,它们被创建为new并与已经存在于其他地方的Person对象分开。 NSMutableArray“参与者”只包含引用,指向Person对象的弱链接,因此条件编码其内容,因为可以在“encodeWithCoder”中手动处理其他对象:
[aCoder encodeConditionalObject:anObject forKey:aKey];
当NSMutableArray被解码时,它应该表示对已经存在的Person对象的引用列表 - 而不是全新的对象!测试“aPerson == [[aDecoder decodeObjectForKey:@”participant“] objectAtIndex:0]”当前返回NO,尽管在编码/解码过程发生之前它已经返回YES。
我希望我的解释在某种程度上是可以理解的,你可以帮助我解决我的问题:)简单来说:我如何条件编码NSMutableArray中包含的自定义对象?
谢谢!
答案 0 :(得分:1)
如果NSMutableArray
对其包含的对象使用encodeConditionalObject:forKey:
,则只是意味着这些对象根本没有编码,如果它们没有在对象图中的其他位置无条件编码。在这种情况下,这对你没有帮助(数组只是空的)。
问题是你无法真正编码对内存中对象的引用。对象引用基本上只是指向内存中地址的指针。当您下次启动应用程序并创建完全相同的对象(无论是通过取消归档还是其他方式)时,它几乎肯定会在内存中具有不同的地址。 unarchiver无法“神奇地”知道哪个现有对象对应于它已归档的引用,因为当您退出应用程序时,内存地址(对象的“身份”)将失去其所有含义。
您必须使用其他方法来识别对象,例如数据库行ID,字典键等,并手动建立存档密钥与该密钥对应的现有对象的连接。
答案 1 :(得分:0)
我也有这个问题。我有一些对象具有一系列弱链接到其他对象。我知道链接到的所有对象都将被编码,所以我只想确保我可以重建链接。
使用单个弱链接可以使用:
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")
如果我移动到数据库来存储东西,我认为这也会有帮助,因为我需要一个单独的表来存储链接并保持优先级等。