Измените объект после возвращения в Swift
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(кодер aDecoder: NSCoder) он вернет этот объект в массиве (строка 174).
Я попытался повторить это поведение в Swift для моей библиотеки. Но я не смог найти способ сделать это в Swift, потому что мы не можем сделать alloc
без init
в Свифте. Любое предложение? Может быть перезапись байтов в указателе объекта будет работать?