Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't my Swift 3.0 decoder decodeInteger work for integers?

Tags:

ios

swift3

So we've been using Groups for saving and retrieving some data across an extension and the main app and everything worked fine for Swift 2.3 but then we updated to Swift 3.0 and got some issues.

The current implementation that gives us issues is like following:

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") 
  }

}

The following error is thrown:

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

The funny thing is the old implementation for Swift 2.3 works without any issues: self.someVar = decoder.decodeObject(forKey: "someVar") as! Int (I've understood from other posts that this would not work...)

So what could I be doing wrong? It should be said that the original value is retrieved from a float and cast to an int.

like image 558
Warpzit Avatar asked Oct 12 '16 13:10

Warpzit


Video Answer


1 Answers

This problem is caused by multiple changes in Swift 3.

In Swift 3 the encode method is overloaded for every type. We have:

encode(Any?, forKey: String)

and

encode(Int, forKey: String)

The compiler chooses the correct method depending on the type of the first parameter (in Swift 2 you had two different method names therefore the type information was not needed).

You are putting Int! there. The behavior for Implicitly Unwrapped Optionals in Swift 3 changed due to Swift Evolution 0054.

If you read the changes, you can note that converting an IUO into a regular optional is preferred over unwrapping, therefore converting to Any? is preferred over unwrapping into Int.

However, the appearance of ! at the end of a property or variable declaration's type no longer indicates that the declaration has IUO type; rather, it indicates that (1) the declaration has optional type, and (2) the declaration has an attribute indicating that its value may be implicitly forced. (No human would ever write or observe this attribute, but we will refer to it as @_autounwrapped.)

The problem should be fixed by

aCoder.encode(self.someVar!, forKey:"someVar")
like image 128
Sulthan Avatar answered Oct 01 '22 03:10

Sulthan