简体   繁体   English

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

[英]NSUserDefaults and Conditional Encoding of Custom Objects in an NSArray

I know there are a lot of posts out there concerning the problem of how to archive custom objects in an NSArray or NSMutableArray and save them in NSUserDefaults. 我知道有很多关于如何在NSArray或NSMutableArray中归档自定义对象并将其保存在NSUserDefaults中的问题。 Conforming to the NSCoding Protocol and saving to NSUserDefaults isn't problematic and I use NSUserDefaults quite a lot to store the user-submitted data in my app - it mostly contains objects representing a Person (let's call the NSObject subclass "Person") which can have multiple objects of the NSObject subclass "Property" stored in an NSMutableArray. 符合NSCoding协议并保存到NSUserDefaults没问题,我在很多情况下都使用NSUserDefaults将用户提交的数据存储在我的应用程序中-它主要包含代表Person的对象(我们将其称为NSObject子类“ Person”),在NSMutableArray中存储了NSObject子类“ Property”的多个对象。 Therefore, the data structure looks like this: 因此,数据结构如下所示:

NSMutableArray "persons":
    Person "aPerson":
        NSMutableArray "properties":
            Property "aProperty"
            Property "anotherProperty"
    Person "anotherPerson:
        ...

Archiving and restoring the information was not problematic at first, because both Person and Property conform to the NSCoding Protocol - but now a problem occured which I was not able to solve yet despite those thousands of google requests in the last couple days ;) 最初,存档和恢复信息没有问题,因为Person和Property都符合NSCoding协议-但现在发生了一个问题,尽管最近几天有成千上万的google请求,但我仍然无法解决;)

Some of the Property objects contain references to other Persons ("Participants", which are linked to the same property and are contained in an NSMutableArray). 一些Property对象包含对其他Person的引用(“参与者”,它们链接到相同的属性,并且包含在NSMutableArray中)。 When I store the whole data to NSUserDefaults using NSKeyedArchiver, I use 当我使用NSKeyedArchiver将整个数据存储到NSUserDefaults时,我使用

[aCoder encodeObject:participants forKey:@"participants"];

in the Property's "encodeWithCoder" method to archive the NSMutableArray "participants" which stores the references to other Person objects. 在属性的“ encodeWithCoder”方法中,可以将存储对其他Person对象的引用的NSMutableArray“参与者”存档。 But when I decode those Person objects, they are created new and separated from the Person objects that already exist somewhere else. 但是,当我解码这些Person对象时,它们是新创建的,并且与其他地方已经存在的Person对象分开。 The NSMutableArray "participants" only contains references , weak links to the Person objects and should therefore conditional encode its content, as one can do with other objects manually in "encodeWithCoder": NSMutableArray“参与者”仅包含引用 ,指向Person对象的弱链接,因此应该有条件地对其内容进行编码 ,就像可以在“ encodeWithCoder”中手动处理其他对象一样:

[aCoder encodeConditionalObject:anObject forKey:aKey];

When the NSMutableArray gets decoded, it should represent a list of references to already existing Person objects - not completely new ones! 当NSMutableArray被解码时,它应该代表对已经存在的Person对象的引用列表-而不是全新的对象! The test "aPerson==[[aDecoder decodeObjectForKey:@"participants"] objectAtIndex:0]" is currently returning NO although it had returned YES before the encoding/decoding process has taken place. 测试“ aPerson == [[aDecoder encodingObjectForKey:@“参与者”] objectAtIndex:0]”当前返回NO,尽管它在进行编码/解码过程之前返回了YES。

I hope my explanation is somehow understandable and you can help me with my problem :) In simple words: How can I conditional encode custom objects contained in an NSMutableArray? 我希望我的解释是可以理解的,并且您可以帮助我解决我的问题:)简单来说:如何对NSMutableArray中包含的自定义对象进行条件编码?

Thank You ! 谢谢 !

If NSMutableArray would use encodeConditionalObject:forKey: for the objects it contains, it would just mean that those objects aren't encoded at all, if they're not encoded unconditionally somewhere else in your object graph. 如果NSMutableArray对它包含的对象使用encodeConditionalObject:forKey:则意味着如果这些对象不是在对象图中的其他地方无条件地编码的,则根本不会被编码。 This wouldn't help you in this case (the array would just be empty). 在这种情况下,这将无济于事(该数组将为空)。

The problem is that you cannot really encode references to objects in memory. 问题是您无法真正编码对内存中对象的引用。 An object reference is basically just a pointer to an address in memory. 对象引用基本上只是指向内存中地址的指针。 When you start your app the next time and create the very same object (whether by unarchiving or otherwise), it will almost definitely have a different address in memory. 下次启动应用程序并创建相同的对象时(无论是通过取消存档还是其他方式),几乎肯定会在内存中具有不同的地址。 There is no way the unarchiver can 'magically' know, which existing object corresponds to the reference it has archived, because the memory address (the object's 'identity') loses all its meaning when you quit your app. 取消存档程序无法“神奇地”知道哪个现有对象与其已存档的引用相对应,因为当您退出应用程序时,内存地址(对象的“身份”)会失去所有含义。

You have to use other means of identifying your objects, such as database row IDs, dictionary keys, etc. and establish the connection of the archived key and the existing object corresponding to that key manually. 您必须使用其他方法来标识您的对象,例如数据库行ID,字典键等,并手动建立已归档键和与该键对应的现有对象的连接。

I had an issue with this too. 我也有这个问题。 I have objects that have an array of weak links to other objects. 我的对象具有与其他对象的一系列弱链接。 I know all the objects linked to will be encoded, so I just want to make sure I can rebuild the links. 我知道链接到的所有对象都会被编码,因此我只想确保可以重建链接。

With a single weak link is it possible to use: 使用单个弱链接可以使用:

aCoder.encodeConditionalObject(thing, forKey: "Thing")

...and if that item has already been encoded from elsewhere, then a reference to that encoded item will be used. ...并且如果该商品已从其他位置进行编码,则将使用对该编码商品的引用。

But, what to do if you have an array full of 'conditional' items, where the array needs to be encoded unconditionally? 但是,如果您有一个充满“条件”项的数组,而该数组需要无条件编码,该怎么办?

I ended up wrapping the items I want to link to. 我最后包装了要链接的项目。

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")
    }
}

...then I store these in my array which I encode as usual. ...然后将它们存储在我通常编码的数组中。

aCoder.encode(things, forKey: "Things")

If I move to a database to store things, I think this will help there too, because I will need a separate table to store the links and maintain priority etc. 如果我移到数据库来存储内容,我认为这也将有所帮助,因为我需要一个单独的表来存储链接并保持优先级等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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