在Swift中返回后更改对象

时间:2018-06-12 03:35:08

标签: ios swift cocoa nscoder

NSKeyedUnarchiver这是NSCoder的具体子类,就像魔法一样。

请看一下这个例子:

我有2个课程,PersonCreditCard

class Person: NSObject, NSCoding {
    var creditCard: CreditCard

    init(coder aDecoder: NSCoder) {
        aDecoder.decodeObject(forKey: "creditCard") as? CreditCard            
    }
}

class CreditCard: NSObject, NSCoding {
    weak var person: Person

    init(coder aDecoder: NSCoder) {
        aDecoder.decodeObject(forKey: "person") as? Person
    }
}

如您所见,对象彼此连接。令NSKeyedUnarchiver令人惊讶的是它如何处理无限循环。如果一个编码器跟随每个链接并盲目地编码它遇到的每个对象,这个循环引用将产生一个无限循环:

Person -> CreditCard -> Person -> CreditCard -> ....infinite loop

以下是步骤:

  1. 初始化Person课程时,会调用aDecoder.decodeObject(forKey: "creditCard") as? CreditCard 此方法调用init(coder aDecoder: NSCoder)类中的CreditCard

  2. 但是CreditCard类无法初始化,因为初始化程序中有aDecoder.decodeObject(forKey: "person")。此方法会在init(coder aDecoder: NSCoder)类中调用Person

  3. 它将无限重复,PersonCreditCard都无法初始化,如鸡蛋和鸡肉。

  4. 我试图找出NSKeyedArchiver如何阻止此循环。

    根据这个:
    https://github.com/gnustep/libs-base/blob/master/Source/NSKeyedUnarchiver.m

    诀窍是使用o = [className allocWithZone: _zone];(第237行)而不使用init并将其存储到数组中。下次当我们调用aDecoder.decodeObject(forKey:)而不是调用init(coder aDecoder:NSCoder)时,它将在数组中返回该对象(第174行)。

    我试图在Swift中为我的库复制这种行为。但我找不到在Swift中执行此操作的方法,因为在Swift中我们无法alloc没有init。有什么建议吗?也许重写对象指针中的字节会起作用吗?

0 个答案:

没有答案