我在写一个名为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" 致命错误:在展开Optional值时意外发现nil 2016-09-30 13:32:55.901189连接[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
}
我想知道什么会导致错误。感谢。
答案 0 :(得分:12)
斯威夫特3:
我正在编码一个double值。使用decoder.containsValue检查值是否已编码。
并使用decodeDouble(forKey :)。不是decodeObject(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")
}
答案 1 :(得分:2)
Swift 4.2:
使用decodeObject(forKey:)
解码基本类型时,它返回nil。由于encode(_:forKey:)
的重载直接采用一个Int并将其写入NSNumber类型,因此您不能将其解码为对象。
decodeInteger(forKey:)
正确地将其读取为Int并将其返回。
您可以改用decodeInteger(forKey:)
,Int(decodeInt32(forKey:))
或Int(decodeInt64(forKey:))
。
答案 2 :(得分:1)
在编码或解码Double和Bool等原始类型时,必须分别使用指定的方法r = n/2
和decodeDouble:forKey
,否则它们将无法解码并返回nil。
答案 3 :(得分:0)
就我而言,我尝试解码的类是 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