encodeWithCoder: 未识别的选择器发送给实例

3

我正在尝试使用NSCoding协议将数据读写到plist中。当我尝试写入[GolfHoles](这是NSObject的一个子类)时,会出现异常。我已经阅读了几篇不同方法的帖子,但都没有帮助。

class GolfCourse: NSObject, NSCoding {
var name: String = ""
var location: String = ""
var holes: [GolfHole] = [GolfHole]()

init(holes: [GolfHole]) {
    self.holes = holes
}

// MARK: NSCoding Protocol
func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(name, forKey: "name")
    aCoder.encodeObject(location, forKey: "location")
    aCoder.encodeObject(holes, forKey: "holes") // exception here

}

required init(coder aDecoder: NSCoder) {
    super.init()
    name = aDecoder.decodeObjectForKey("name") as! String
    location = aDecoder.decodeObjectForKey("location") as! String
    holes = aDecoder.decodeObjectForKey("holes") as! [GolfHole]

}

override init() {
    super.init()
    for var i=0; i<18; i++ {
        let newHole = GolfHole()
        self.holes.append(newHole)

    }
}

如何编写和读取数组?


2
无法决定是将其视为重复项而投票关闭,还是因未提供异常说明而投票关闭。无论哪种方式,都应该关闭。 - Hot Licks
也许应该投票关闭问题,因为没有阅读 iOS 标签 wiki :-o ... 它说:“在发布任何与应用程序崩溃相关的问题之前,请先阅读 Ray Wenderlich 的文章 My App crashed. Now what?。它解释了如何正确调试 iOS 应用程序。如果您没有 适当的 回溯和异常消息,那么提出与崩溃相关的问题是毫无意义的。” - Michael
2
你的 GolfHole 类是否符合 NSCoding 协议?它需要像你的 GolfCourse 类一样实现这两个协议方法。 - rmaddy
要查看导致错误的实际语句,请添加异常断点:
  1. 从主菜单调试:断点:创建异常断点。
  2. 右键单击断点并将异常设置为Objective-C。
  3. 添加操作:“po $arg1”。
运行应用程序以获取断点,您将在导致异常的行处,并且错误消息将在调试器控制台中。断点示例:
- zaph
谢谢你,rmaddy。我没能让GolfHole类符合NSCoding协议。 - user2966301
这个问题不是 https://dev59.com/9V8e5IYBdhLWcg3wVJIC 的重复,因为后者是关于如何调试一般的未识别选择器异常。而这个问题是关于 NSCoding 实现的,虽然它没有堆栈跟踪或异常消息,但已经有了很好的答案。 - Vladimir
1个回答

9

rmaddy是正确的。你需要让所有要保存的类也符合NSCoding协议。这里有一个GolfHole类的简单示例,以及如何序列化GolfCourse对象。

class GolfHole: NSObject, NSCoding {
  let number: Int
  let par: Int

  init(number: Int, par: Int) {
    self.number = number
    self.par = par
  }

  convenience required init?(coder aDecoder: NSCoder) {
    guard
      let number = aDecoder.decodeObjectForKey("number") as? Int,
      let par    = aDecoder.decodeObjectForKey("par")    as? Int
    else {
      return nil
    }
    self.init(number: number, par: par)
  }

  func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(number, forKey: "number")
    aCoder.encodeObject(par,    forKey: "par")
  }
}


class GolfCourse: NSObject, NSCoding {
  var name = ""
  var location = ""
  var holes = [GolfHole]()

  init(name: String, location: String, holes: [GolfHole]) {
    self.name = name
    self.location = location
    self.holes = holes
  }

  convenience required init?(coder aDecoder: NSCoder) {
    guard
      let name     = aDecoder.decodeObjectForKey("name")     as? String,
      let location = aDecoder.decodeObjectForKey("location") as? String,
      let holes    = aDecoder.decodeObjectForKey("holes")    as? [GolfHole]
    else {
      return nil
    }
    self.init(name: name, location: location, holes: holes)
  }

  func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(name,     forKey: "name")
    aCoder.encodeObject(location, forKey: "location")
    aCoder.encodeObject(holes,    forKey: "holes")
  }
}

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接