所以我们一直在使用Groups来保存和检索扩展程序和主应用程序中的一些数据,一切都适用于Swift 2.3但我们更新到Swift 3.0并遇到了一些问题。
给我们带来问题的当前实现如下:
open class SomeClass: NSObject, NSCoding {
open var someVar: Int!
open func encode(with aCoder: NSCoder) {
aCoder.encode(self.someVar, forKey:"someVar")
}
public required convenience init?(coder decoder: NSCoder) {
// this is where it breaks
self.someVar = decoder.decodeInteger(forKey: "someVar")
}
}
抛出以下错误:
*** Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: '*** -[NSKeyedUnarchiver decodeInt32ForKey:]: value for key (someVar) is not an integer number'
有趣的是,Swift 2.3的旧版实现没有任何问题:self.someVar = decoder.decodeObject(forKey: "someVar") as! Int
(我从其他帖子中了解到这不起作用......)
那么我可能做错了什么?应该说原始值是从float中检索并转换为int。
答案 0 :(得分:9)
此问题是由Swift 3中的多个更改引起的。
在Swift 3中,每种类型的encode
方法都会重载。我们有:
encode(Any?, forKey: String)
和
encode(Int, forKey: String)
编译器根据第一个参数的类型选择正确的方法(在Swift 2中,您有两个不同的方法名称,因此不需要类型信息)。
你将Int!
放在那里。由于Swift Evolution 0054,Swift 3中Implicitly Unwrapped Optionals的行为发生了变化。
如果您阅读了更改,则可以注意到,将IUO转换为常规可选项比首次展开更受欢迎,因此优先转换为Any?
而不是展开到Int
。
但是,外观!在属性或变量声明类型的末尾不再表示声明具有IUO类型;相反,它表示(1)声明具有可选类型,(2)声明具有一个属性,指示可以隐式强制其值。 (没有人会写或观察这个属性,但我们会将其称为@_autounwrapped。)
问题应该由
解决aCoder.encode(self.someVar!, forKey:"someVar")
答案 1 :(得分:4)
首先检查您是否使用旧版本的swift编码数据,如果是这种情况,您仍然需要使用
aDecoder.decodeObject(forKey: "someVar")
因此,在这种情况下,更完整的解决方案将是
aDecoder.decodeObject(forKey: "age") as? Int ?? aDecoder.decodeInteger(forKey: "age")
如果情况并非如此,那么请确保" someVar"实际上有一个值集