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.
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")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With