Swift: Does not conform to protocol NSCoding
Asked Answered
G

3

13

I am trying to use the NSCoding protocol on a class I have written in swift, but cannot seem to figure out why the compiler complains that it "does not conform to protocol NSCoding" when I do implement the required methods:

class ServerInfo: NSObject, NSCoding {

    var username = ""
    var password = ""
    var domain = ""
    var location = ""
    var serverFQDN = ""
    var serverID = ""

    override init() {

    }

    init(coder aDecoder: NSCoder!) {
        self.username = aDecoder.decodeObjectForKey("username") as NSString
        self.password = aDecoder.decodeObjectForKey("password") as NSString
        self.domain = aDecoder.decodeObjectForKey("domain") as NSString
        self.location = aDecoder.decodeObjectForKey("location") as NSString
        self.serverFQDN = aDecoder.decodeObjectForKey("serverFQDN") as NSString
        self.serverID = aDecoder.decodeObjectForKey("serverID") as NSString
    }


    func encodeWithCoder(_aCoder: NSCoder!) {
        _aCoder.encodeObject(self.username, forKey: "username")
        _aCoder.encodeObject(self.password, forKey: "password")
        _aCoder.encodeObject(self.domain, forKey: "domain")
        _aCoder.encodeObject(self.location, forKey: "location")
        _aCoder.encodeObject(self.serverFQDN, forKey: "serverFQDN")
        _aCoder.encodeObject(self.serverID, forKey: "serverID")
    }

}

Is this a bug or am I just missing something?

Glassy answered 9/9, 2014 at 16:54 Comment(0)
C
19

As you can see in the detailed compiler messages in the Report navigator, your methods are not declared correctly:

error: type 'ServerInfo' does not conform to protocol 'NSCoding'
class ServerInfo: NSObject, NSCoding {
^
Foundation.NSCoding:2:32: note: protocol requires function 'encodeWithCoder' with type '(NSCoder) -> Void'
  @objc(encodeWithCoder:) func encodeWithCoder(aCoder: NSCoder)
                               ^
note: candidate has non-matching type '(NSCoder!) -> ()'
    func encodeWithCoder(_aCoder: NSCoder!) {
         ^
Foundation.NSCoding:3:25: note: protocol requires initializer 'init(coder:)' with type '(coder: NSCoder)'
  @objc(initWithCoder:) init(coder aDecoder: NSCoder)
                        ^
note: candidate has non-matching type '(coder: NSCoder!)'
    init(coder aDecoder: NSCoder!) {

(This may have changed between the beta releases.) In addition, the initWithCoder method has to be marked as required:

required init(coder aDecoder: NSCoder) {   }

func encodeWithCoder(_aCoder: NSCoder) {   }

In Swift 3 the required methods are

required init(coder aDecoder: NSCoder) {   }

func encode(with aCoder: NSCoder) {   }
Cheddar answered 9/9, 2014 at 17:4 Comment(7)
"This may have changed between the beta releases" Yes, one wants to scream at Swift, "Dude, I got these method signatures from you! How dare you tell me that now they're wrong!?" But of course that's life in the fast-paced beta lane...Rois
@matt: At least the compiler prints a sensible message here, instead of "$%§?& cannot be converted to UInt8" :)Cheddar
Except that half the time the parameter it complains about is the wrong one! :))Rois
hey Martin i have marked the initWithCode as required but still i see the same error. Also another issue i am facing is encodeWithCoder is not called.Frons
@KunalGupta: Are you using Swift 3/Xcode 8? The signature of the encode method changed, see updated answer.Cheddar
@MartinR thanks.. buddy :) .. Yeah i am using the Swift 3/ xcode 8... Why the hell they changed the method name. I wasted my 2 days.Frons
@KunalGupta: A lot changed with Swift 3, see swift.org/migration-guide. This particular change is part of github.com/apple/swift-evolution/blob/master/proposals/….Cheddar
S
4

The parameters are not implicitly unwrapped (remove the !), and the initializer requires the required modifier:

required init(coder aDecoder: NSCoder) {
...
func encodeWithCoder(_aCoder: NSCoder) {

For Swift 3

A minor but important change has been commited . The init method is same but the encodeWithCoder method has been modified.

   required init(coder aDecoder: NSCoder) {
    ...
   }

   func encode(with _aCoder: NSCoder) { 
   ...
   }
Spirited answered 9/9, 2014 at 17:4 Comment(0)
M
0

For Swift 3 (on Xcode 8.2 beta (8C23))

It appears to have changed again. This is the only variation that I could get to work...

func encodeWithCoder(_ _aCoder: NSCoder) {
    ...
}
Mesitylene answered 12/11, 2016 at 12:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.