【问题标题】:-[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance-[_SwiftValue encodeWithCoder:]:发送到实例的无法识别的选择器
【发布时间】:2017-02-14 06:45:49
【问题描述】:

尝试使用 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")
    }

}

在 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
    }

}

【问题讨论】:

  • 你不能直接编码枚举,比较stackoverflow.com/questions/26471265/swift-enum-and-nscoding - 重复?
  • 顺便说一句,Swift 中不需要你的 getter、setter 和下划线变量(就像在其他一些语言中一样)。除非您有特殊需要,否则只是var playerName: String 等。

标签: ios swift nsuserdefaults swift3 nscoder


【解决方案1】:

您也可以使用 Enum rawValue 来使用这种方法。它可能会帮助您将archivedData 和unarchiveObject 变成一个完整的模型对象。

具有十六进制值的颜色枚举:

enum PlayerColor: String {
    case red = "#FF0000"
    case silver = "#C0C0C0"
    case gray = "#808080"
    case black = "#000000"

    var description: String {
        return self.rawValue
    }
}

 import Foundation

class Player: NSObject, NSCoding {

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

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

        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

        if let value = aDecoder.decodeObject(forKey: "color") as? String{
            color = PlayerColor(rawValue: value)
        }
        self.init(playerName: name, playerScore: score, playerColor: color)
    }

    func encode(with aCoder: NSCoder){

        aCoder.encode(name, forKey: "name")
        aCoder.encode(score, forKey: "score")

        let value = color!.description
        aCoder.encode(value, forKey: "color")
    }

}

【讨论】:

    【解决方案2】:

    这是我实施的解决方案:

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

    【讨论】:

    • 我有两个浏览器和这篇文章的链接。我试图弄清楚有什么不同?另外,为什么你所做的任何改变都有帮助?
    • @ScottyBlades OP 删除了自定义 PlayerColor-enum 并用 String 进行了更改。如上所述,枚举无法编码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-09
    • 2017-01-23
    • 1970-01-01
    • 1970-01-01
    • 2019-08-28
    • 2012-07-24
    相关资源
    最近更新 更多