【问题标题】:swift: nscoding decodeObject with nil all the timeswift: nscoding decodeObject 一直都是 nil
【发布时间】:2017-02-08 14:50:24
【问题描述】:

我得到以下代码来编写一个名为 Packet 的对象并通过 Multipeer 连接发送到另一端。但是,每当它尝试解码编码对象时,我都会收到以下错误。

  class Packet : NSObject, NSCoding {

  var tmp1: Double = 0
  var tmp2: Double = 0

  struct PropertyKey {
    static let tmp1Key = "tmp1Key"
    static let tmp2Key = "tmp2Key"
  }


  init(tmp1: Double, tmp2: Double) {
    self.tmp1 = tmp1
    self.tmp2 = tmp2
    super.init()
  }

  deinit {
  }

  required convenience init(coder aDecoder: NSCoder) {
    debugPrint("initcoder")
    let tmp1 = aDecoder.decodeObject(forKey: PropertyKey.tmp1Key) as! Double // crash here
    let tmp2 = aDecoder.decodeObject(forKey: PropertyKey.tmp2Key) as! Double
    self.init(tmp1: tmp1, tmp2: tmp2)
  }

  public func encode(with aCoder: NSCoder) {
    debugPrint("encodeCoder")
    aCoder.encode(tmp1, forKey: PropertyKey.tmp1Key)
    aCoder.encode(tmp2, forKey: PropertyKey.tmp2Key)
  }
}

我得到的错误是 ----从我这里打印出来----“initcoder” 致命错误:在展开可选值时意外发现 nil 2016-09-30 13:32:55.901189 Connection[323:33022] 致命错误:在展开可选值时意外发现 nil

但是当我构造对象时,所有的值都设置好了。 我毫无问题地承包了一个 Packet 对象。

---- 附加信息 ------ 当通过乘法器连接发送到另一端时,我使用以下代码对数据进行编码和解码。

 func dataForPacket(packet: Packet) -> Data {
    let data = NSMutableData()
    let archiver = NSKeyedArchiver(forWritingWith: data)
    archiver.encode(packet, forKey: "Packet")
    archiver.finishEncoding()
    debugPrint("dataForPacket \(data) \(packet)")
    return data as Data
  }

  func packetForData(_ data: Data) -> Packet {
    debugPrint("packetForData")
    let unarchiver = NSKeyedUnarchiver(forReadingWith: data)

    let packet: Packet = unarchiver.decodeObject(forKey: "Packet") as! Packet 
     // crash here (as this will call the init of the Packet class)
    debugPrint("packetForData \(packet)")
    return packet
  }

我想知道什么会导致错误。谢谢。

【问题讨论】:

  • 你需要使用decodeDouble作为key
  • let tmp1 = aDecoder.decodeDouble(forKey: PropertyKey.tmp1Key)
  • 正如上述 cmets 所提到的,您必须对整数、浮点数、布尔值、双精度数等使用特定的解码。
  • 非常感谢!!它解决了我的问题!
  • 我发现了另一个问题:当我的类 Packet 具有其他类型的类变量(例如,数组、UIViews)时,我对 tmp1 和 tmp2 使用了 decodeDouble,然后对其他类型使用了 decodeObject。然后它崩溃并说 tmp1 和 tmp2 不是 Double 类型(虽然它们实际上是 Double 类型)。当我将它们更改为 decodeObject 时,它不再崩溃。为什么会这样?

标签: ios swift nscoding multipeer-connectivity nskeyedunarchiver


【解决方案1】:

斯威夫特 3:

我正在编码一个双精度值。使用 decoder.containsValue 检查值是否已编码。

并使用 decodeDouble(forKey:)。不解码对象(forKey:)

 var dateTime: TimeInterval = SOME_TIME_INTERVAL (Double)//Can be saved(encoded) previously, and not encoded as well.
 aCoder.encode(dateTime, forKey: "dateTime")
 if decoder.containsValue(forKey: "dateTime") {
            dateTime = decoder.decodeDouble(forKey: "dateTime")
        }

【讨论】:

  • 注意:解码Strings时,使用decodeObject(forKey:)
【解决方案2】:

斯威夫特 4.2:

当使用decodeObject(forKey:) 解码原始类型时,它返回 nil。因为encode(_:forKey:)的重载直接取了一个Int,写成NSNumber类型,无法解码为对象。

decodeInteger(forKey:) 将其正确读取为 Int 并返回。 您可以改用decodeInteger(forKey:)Int(decodeInt32(forKey:))Int(decodeInt64(forKey:))

【讨论】:

    【解决方案3】:

    在对Double和Bool等基本类型进行编码或解码时,必须分别使用指定的方法decodeDouble:forKeydecodeBool:forKey,否则它们将无法解码并返回nil。

    【讨论】:

      【解决方案4】:

      在我的例子中,我试图解码的类是一个 NSDictionary,在我重构我的代码以在 Swift 5.3 的 NSKeyedUnarchiver 中使用非弃用函数后,它一直返回为 nil。

      当我尝试解码对象时,它始终为 nil,即使以下代码返回 true:

      unarchiver.containsValue(forKey: saveKey)
      

      我发现了问题。如果我使用新的非弃用函数,它会起作用:

      工作代码:

      let unarchiver = try NSKeyedUnarchiver(forReadingWith: data)  // forReadingWith now has a deprecated warning.. ?? but the alternative does not work.
      var unarchived = unarchiver.decodeObject(forKey: saveKey) // nil
      

      BROKEN 代码 - 不起作用,但使用了不推荐使用的功能:

      let unarchiver = try NSKeyedUnarchiver(forReadingFrom: data)
      var unarchived = unarchiver.decodeObject(forKey: saveKey) // not nil - works
      

      【讨论】:

      • 您是否找到了涉及使用现代(非弃用)API 的解决方案?想知道,因为我们想读取以前保存的数据,我仍然看到nil。 @TheJeff
      • 确保您也使用非弃用函数编写代码
      • decodeTopLevelObject 为我解决了这个问题
      猜你喜欢
      • 2019-12-22
      • 2018-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-17
      相关资源
      最近更新 更多