繁体   English   中英

NSArray中的NSUserDefaults和自定义对象的条件编码

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM