NSKeyedUnarchiver
这是NSCoder
的具体子类,就像魔法一样。
请看一下这个例子:
我有2个课程,Person
和CreditCard
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
以下是步骤:
初始化Person
课程时,会调用aDecoder.decodeObject(forKey: "creditCard") as? CreditCard
此方法调用init(coder aDecoder: NSCoder)
类中的CreditCard
。
但是CreditCard
类无法初始化,因为初始化程序中有aDecoder.decodeObject(forKey: "person")
。此方法会在init(coder aDecoder: NSCoder)
类中调用Person
。
它将无限重复,Person
和CreditCard
都无法初始化,如鸡蛋和鸡肉。
我试图找出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
。有什么建议吗?也许重写对象指针中的字节会起作用吗?