当使用NSCoding
或NSKeyedArchiver
作为父子关系时;我无法为孩子提供一个参考,因为它最终会在Swift Playground上崩溃。NSCoding - 保存父属性导致崩溃
我想在我的Child
类中为我的Parent
类提供参考。
但是当它将数据加载回内存时,它最终会在Playground上崩溃。
class Parent: NSObject, NSCoding {
var children:[Child] = [Child]()
init(children:[Child]?) {
if let childrenList = children {
self.children = childrenList
}
}
public convenience required init?(coder aDecoder: NSCoder) {
let children = aDecoder.decodeObject(forKey: "children") as! [Child]
self.init(children: children)
}
func encode(with aCoder: NSCoder) {
aCoder.encode(children, forKey:"children")
}
}
class Child: NSObject, NSCoding {
var parent: Parent
init(parent:Parent) {
self.parent = parent
}
public convenience required init?(coder aDecoder: NSCoder) {
let parent = aDecoder.decodeObject(forKey: "parent") as! Parent
self.init(parent: parent)
}
func encode(with aCoder: NSCoder) {
aCoder.encode(parent, forKey:"parent")
}
}
var parent1 = Parent.init(children: nil)
var parent2 = Parent.init(children: nil)
var child1 = Child.init(parent: parent1)
var child2 = Child.init(parent: parent2)
parent1.children.append(child1)
parent2.children.append(child2)
let parents = [parent1, parent2]
let manager = FileManager.default
let url = manager.urls(for: .documentDirectory, in: .userDomainMask).first! as URL
let writeFile: URL = url.appendingPathComponent("sample.data")
print ("Attempting to write to: \(writeFile.path)")
NSKeyedArchiver.archiveRootObject(parents, toFile: writeFile.path)
// Crash occurs here.
if let parentData = NSKeyedUnarchiver.unarchiveObject(withFile: writeFile.path) as? [Parent] {
for p in parentData {
print ("\(p.children.count)")
}
}
在Child
类中,我想引用父类;以便将来我可以对某些父母进行测试或筛选子对象。
但是,我总是在操场上此崩溃:
Playground execution aborted: error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x10). The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
这似乎崩溃的参考父对象。
如何确保NSCoding将我的父属性保存在子对象中?
非常感谢
编辑:重构代码
这个重构的代码似乎工作,虽然我不知道我是否做对事。
class Parent: NSObject, NSCoding {
private (set) var children:[Child] = [Child]()
override init() {
super.init()
}
public convenience required init?(coder aDecoder: NSCoder) {
let children = aDecoder.decodeObject(forKey: "children") as! [Child]
self.init()
self.createChildren(children: children)
}
func encode(with aCoder: NSCoder) {
aCoder.encode(children, forKey:"children")
}
func addChild(child:Child) {
child.parent = self
self.children.append(child)
}
private func createChildren(children:[Child]) {
for child:Child in children {
self.addChild(child: child)
}
}
}
class Child: NSObject, NSCoding {
weak var parent: Parent?
override init() {
super.init()
}
public convenience required init?(coder aDecoder: NSCoder) {
self.init()
}
func encode(with aCoder: NSCoder) {
}
}
var parent1 = Parent.init()
var parent2 = Parent.init()
var child1 = Child.init()
var child2 = Child.init()
parent1.addChild(child: child1)
parent2.addChild(child: child2)
let parents = [parent1, parent2]
let manager = FileManager.default
let url = manager.urls(for: .documentDirectory, in: .userDomainMask).first! as URL
let writeFile: URL = url.appendingPathComponent("sample.data")
print ("Attempting to write to: \(writeFile.path)")
NSKeyedArchiver.archiveRootObject(parents, toFile: writeFile.path)
if let parentData = NSKeyedUnarchiver.unarchiveObject(withFile: writeFile.path) as? [Parent] {
for p in parentData {
print ("\(p.children.count)")
}
}
好的,我会尝试重构我的代码。将父母引用为弱引用的建议是很好的建议。我没有想到这一点。我会尝试重构我的代码,看看我在哪里 – zardon
我重构了我的代码。(1)将'children'设为私有(设置)var, (2)子对象不编码/解码父项 (3)函数添加子项,其中设置父项属性 (4)父属性为'weak ' 代码不再崩溃,尽管我不知道我是否做得正确。 – zardon