Swift 无法取消归档数据

Swift can't unarchive Data

我有一个 UIView 子class,其中包含以下内容:

class someClass: UIView {
  var someString = ""
  var imageView: UIImageView
  var position: CGPoint
  var dimensions: CGFloat

  init(position: CGPoint, dimensions: CGFloat, someString: String) {
    self.position = position
    self.dimensions = dimensions
    self.someString = someString
    self.imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: dimensions, height: dimensions))
    super.init(frame: CGRect(x: position.x, y: position.y, width: dimensions, height: dimensions))
    addSubview(imageView)
  }
}

我还添加了 required init?(coder aDecoder: NSCoder)encodeWithCoder(coder: NSCoder):

required init?(coder aDecoder: NSCoder) {
  self.someString = aDecoder.decodeObject(forKey: "someString") as! String
  self.position = aDecoder.decodeObject(forKey: "position") as! CGPoint
  self.dimensions = aDecoder.decodeObject(forKey: "dimensions") as! CGFloat
  self.imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: dimensions, height: dimensions))
  super.init(frame: CGRect(x: position.x, y: position.y, width: dimensions, height: dimensions))
  self.addSubview(imageView)
}

func encodeWithCoder(coder: NSCoder) {
  coder.encode(self.position, forKey: "position")
  coder.encode(self.dimensions, forKey: "dimensions")
  coder.encode(self.someString, forKey: "someString")
}

所以,我创建了一个对象 class:

let someObject = someClass(position: CGPoint(x: 2.0, y: 3.0), dimensions: 10.0, someString: "Hello")

我正在尝试存档对象:

let archivedObject = NSKeyedArchiver.archivedData(withRootObject: someObject)

然后取消存档:

let unarchivedObject = NSKeyedUnarchiver.unarchiveObject(with: archivedObject) as! someClass

这里出现错误:

my error

如果打印 unarchivedObject,它将是 "fatal error: unexpectedly found nil while unwrapping an Optional value"。

有人可以帮我解决这个问题吗?怎么了?

看来问题是您没有正确覆盖 encodeWithEncoder。如果你在该函数中放置一个断点,你会发现它永远不会被调用,这就是为什么当你尝试解码它时对象为 nil - 它从未被编码!

您还会 运行 尝试在 CGPoint 上使用 decodeObject 时出错。确保也更改该行,然后您应该开始营业了。

顺便说一句,通常的做法是将 class 名称大写,以便它们与 class 的实例不同,因此我将 someClass 更改为 SomeClass .

class SomeClass: UIView {
var someString = ""
var imageView: UIImageView
var position: CGPoint
var dimensions: CGFloat

init(position: CGPoint, dimensions: CGFloat, someString: String) {
    self.position = position
    self.dimensions = dimensions
    self.someString = someString
    self.imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: dimensions, height: dimensions))
    super.init(frame: CGRect(x: position.x, y: position.y, width: dimensions, height: dimensions))
    addSubview(imageView)
}

required init?(coder aDecoder: NSCoder) {
    self.someString = aDecoder.decodeObject(forKey: "someString") as! String
    self.position = aDecoder.decodeCGPoint(forKey: "position")
    self.dimensions = aDecoder.decodeObject(forKey: "dimensions") as! CGFloat
    self.imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: dimensions, height: dimensions))
    super.init(frame: CGRect(x: position.x, y: position.y, width: dimensions, height: dimensions))
    self.addSubview(imageView)
}

override func encode(with aCoder: NSCoder) {
    aCoder.encode(self.position, forKey: "position")
    aCoder.encode(self.dimensions, forKey: "dimensions")
    aCoder.encode(self.someString, forKey: "someString")
}

}