为什么我的Swift 3.0解码器decodeInteger不能用于整数?

War*_*zit 6 ios swift3

所以我们一直在使用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") 
  }

}
Run Code Online (Sandbox Code Playgroud)

抛出以下错误:

*** Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: '*** -[NSKeyedUnarchiver decodeInt32ForKey:]: value for key (someVar) is not an integer number'
Run Code Online (Sandbox Code Playgroud)

有趣的是Swift 2.3的旧版实现没有任何问题:( self.someVar = decoder.decodeObject(forKey: "someVar") as! Int我从其他帖子中了解到这不起作用......)

那么我可能做错了什么?应该说原始值是从float中检索并转换为int.

Sul*_*han 9

此问题是由Swift 3中的多个更改引起的.

在Swift 3中,该encode方法对于每种类型都是重载的.我们有:

encode(Any?, forKey: String)
Run Code Online (Sandbox Code Playgroud)

encode(Int, forKey: String)
Run Code Online (Sandbox Code Playgroud)

编译器根据第一个参数的类型选择正确的方法(在Swift 2中,您有两个不同的方法名称,因此不需要类型信息).

你在Int!那里.由于Swift Evolution 0054,Swift 3中Implicitly Unwrapped Optionals的行为发生了变化.

如果您阅读了更改,您可以注意到,将IUO转换为常规可选项比首次打包更可取,因此转换Any?为优先于展开Int.

但是,外观!在属性或变量声明的类型末尾不再表示声明具有IUO类型; 相反,它表示(1)声明具有可选类型,(2)声明具有一个属性,指示可以隐式强制其值.(没有人会写或观察这个属性,但我们会将其称为@_autounwrapped.)

这个问题应该由

aCoder.encode(self.someVar!, forKey:"someVar")
Run Code Online (Sandbox Code Playgroud)


小智 5

首先检查您是否使用旧版本的swift编码数据,如果是这种情况您仍然需要使用 aDecoder.decodeObject(forKey: "someVar")

所以在这种情况下更完整的解决方案是

aDecoder.decodeObject(forKey: "age") as? Int ?? aDecoder.decodeInteger(forKey: "age")
Run Code Online (Sandbox Code Playgroud)

如果不是这种情况,请确保“someVar”实际上设置了一个值