Macness Macness - 1 month ago 47
iOS Question

-[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance

Getting error when trying to utilize NSCoder

Player.swift:

class Player: NSObject, NSCoding {

private var _playerName: String!
private var _playerScore: Int!
private var _playerColor: PlayerColor! //PlayerColor is an enum

var playerName: String {
get {
return _playerName
}
set {
_playerName = newValue
}
}

var playerScore: Int {
get {
return _playerScore
}
set {
_playerScore = newValue
}
}

var playerColor: PlayerColor {
get {
return _playerColor
}
set {
_playerColor = newValue
}
}

init(playerName: String, playerScore: Int, playerColor: PlayerColor) {

_playerName = playerName
_playerScore = playerScore
_playerColor = playerColor
}

required convenience init(coder aDecoder: NSCoder) {
let name = aDecoder.decodeObject(forKey: "name") as! String
let score = aDecoder.decodeInteger(forKey: "score")
let color = aDecoder.decodeObject(forKey: "color") as! PlayerColor
self.init(playerName: name, playerScore: score, playerColor: color)
}

func encode(with aCoder: NSCoder){
aCoder.encode(playerName, forKey: "name")
aCoder.encode(playerScore, forKey: "score")
aCoder.encode(playerColor, forKey: "color")
}

}


in PlayerStore.swift:

// Storage Functions
func savePlayers(){
let encodedData = NSKeyedArchiver.archivedData(withRootObject: _playerArray) // _playerarray is a [Player] the very object I want to store/retrieve at will
defaults.set(encodedData, forKey: playerKeyForDefaults) //defaults is just var NSUserDefaults.standard
defaults.synchronize()
}

func loadPlayers(){
if let decoded = defaults.object(forKey: playerKeyForDefaults) as? NSData {
let array = NSKeyedUnarchiver.unarchiveObject(with: decoded as Data) as! [Player]
_playerArray = array
}

}

Answer

Here's the solution I implemented:

Player.swift:

import Foundation

    class Player: NSObject, NSCoding {

        private var name: String!
        private var score: Int!
        private var color: String!

        var playerName: String {
            get {
                return name
            }
            set {
                name = newValue
            }
        }

        var playerScore: Int {
            get {
                return score
            }
            set {
                score = newValue
            }
        }

        var playerColor: String {
            get {
                return color
            }
            set {
                color = newValue
            }
        }

        init(playerName: String, playerScore: Int, playerColor: String) {

            name = playerName
            score = playerScore
            color = playerColor
        }

        required convenience init(coder aDecoder: NSCoder) {
            let name = aDecoder.decodeObject(forKey: "name") as! String
            let score = aDecoder.decodeObject(forKey: "score") as! Int
            let color = aDecoder.decodeObject(forKey: "color") as! String
            self.init(playerName: name, playerScore: score, playerColor: color)
        }

        func encode(with aCoder: NSCoder){
            aCoder.encode(name, forKey: "name")
            aCoder.encode(score, forKey: "score")
            aCoder.encode(color, forKey: "color")
        }

    }

PlayerStore.swift:

func savePlayers(){
    let encodedData = NSKeyedArchiver.archivedData(withRootObject: _playerArray)
    defaults.set(encodedData, forKey: playerKeyForDefaults)
}

func loadPlayers(){
    if let decoded = defaults.object(forKey: playerKeyForDefaults) as? NSData {
        let array = NSKeyedUnarchiver.unarchiveObject(with: decoded as Data) as! [Player]
        _playerArray = array
    }

}
Comments