- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
当使用 NSCoding
或 NSKeyedArchiver
建立父子关系时;我无法在子项中设置对父项的引用,因为它最终会在 Swift Playground 上崩溃。
我想在我的 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
类中,我想引用父类;以便将来我可以与某些 parent 一起对子对象进行测试或过滤。
但是,我总是在 Playground 上遇到这个崩溃:
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)")
}
}
最佳答案
仔细思考您的代码中当前发生的事情。您存档父级。 parent 存档其 child 。然后,这些 child 中的每一个都试图存档其 parent 。然后每个 parent 都试图存档其 child 。这个循环然后继续下去,直到它“繁荣”。
你有几个问题:
Child
类中,parent
属性需要weak
。否则,您会遇到引用循环和大量内存问题。子
类不应尝试编码/解码其父类。Parent
类应该在解码父级时将自己设置为每个子级的父级。您的崩溃是由于违反问题 2 导致的。
作为问题 3 的旁注,我将重构您的代码。创建 child 时不要传递 parent 。并且不要直接在您的 Parent
类中公开 children
数组。我会向 Parent
类添加方法以添加和获取子项。添加子项的方法应设置添加到其中的每个子项的 parent
属性。
关于arrays - NSCoding - 保存父属性导致崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41538831/
你能比较一下属性吗 我想禁用文本框“txtName”。有两种方式 使用javascript,txtName.disabled = true 使用 ASP.NET, 哪种方法更好,为什么? 最佳答案 我
Count 属性 返回一个集合或 Dictionary 对象包含的项目数。只读。 object.Count object 可以是“应用于”列表中列出的任何集合或对
CompareMode 属性 设置并返回在 Dictionary 对象中比较字符串关键字的比较模式。 object.CompareMode[ = compare] 参数
Column 属性 只读属性,返回 TextStream 文件中当前字符位置的列号。 object.Column object 通常是 TextStream 对象的名称。
AvailableSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。 object.AvailableSpace object 应为 Drive 
Attributes 属性 设置或返回文件或文件夹的属性。可读写或只读(与属性有关)。 object.Attributes [= newattributes] 参数 object
AtEndOfStream 属性 如果文件指针位于 TextStream 文件末,则返回 True;否则如果不为只读则返回 False。 object.A
AtEndOfLine 属性 TextStream 文件中,如果文件指针指向行末标记,就返回 True;否则如果不是只读则返回 False。 object.AtEn
RootFolder 属性 返回一个 Folder 对象,表示指定驱动器的根文件夹。只读。 object.RootFolder object 应为 Dr
Path 属性 返回指定文件、文件夹或驱动器的路径。 object.Path object 应为 File、Folder 或 Drive 对象的名称。 说明 对于驱动器,路径不包含根目录。
ParentFolder 属性 返回指定文件或文件夹的父文件夹。只读。 object.ParentFolder object 应为 File 或 Folder 对象的名称。 说明 以下代码
Name 属性 设置或返回指定的文件或文件夹的名称。可读写。 object.Name [= newname] 参数 object 必选项。应为 File 或&
Line 属性 只读属性,返回 TextStream 文件中的当前行号。 object.Line object 通常是 TextStream 对象的名称。 说明 文件刚
Key 属性 在 Dictionary 对象中设置 key。 object.Key(key) = newkey 参数 object 必选项。通常是 Dictionary 
Item 属性 设置或返回 Dictionary 对象中指定的 key 对应的 item,或返回集合中基于指定的 key 的&
IsRootFolder 属性 如果指定的文件夹是根文件夹,返回 True;否则返回 False。 object.IsRootFolder object 应为&n
IsReady 属性 如果指定的驱动器就绪,返回 True;否则返回 False。 object.IsReady object 应为 Drive&nbs
FreeSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。只读。 object.FreeSpace object 应为 Drive 对象的名称。
FileSystem 属性 返回指定的驱动器使用的文件系统的类型。 object.FileSystem object 应为 Drive 对象的名称。 说明 可
Files 属性 返回由指定文件夹中所有 File 对象(包括隐藏文件和系统文件)组成的 Files 集合。 object.Files object&n
我是一名优秀的程序员,十分优秀!