保存Enum类型的字典数组,NSCoding

问题描述 投票:0回答:2

我一直在尝试弄清楚如何使用带有 NSCoding 的枚举类型来保存字典数组。

我有一个包含奖牌类型的枚举

enum Medal: String {
   case Unearned = "NoMedal"
   case Gold = "GoldMedal"
   case Silver = "SilverMedal"
}

我的 GameData.swift 类中有一系列包含奖牌类型的字典。

var medals: [[String: Medal]] = [
    ["1": .Unearned, "2": .Unearned, "3": .Unearned]
    ...
]

我在解码器方法中有这段代码

convenience required init?(coder decoder: NSCoder) {
    self.init()

    medals = decoder.decodeObjectForKey(Key.medals) as? [[String: Medal]] ?? medals
}

这是编码器方法,我认为这是导致我出现问题的原因

// MARK: - Encode
func encodeWithCoder(encoder: NSCoder) {

    encoder.encodeObject(medals as? AnyObject, forKey: Key.medals)
}

问题是重新启动时它不会保存/加载奖牌数组,它会不断重置为默认值。

我也试过这个

 encoder.encodeObject(medals as? [[String: Medal]], forKey: Key.medals)

它会导致编译器错误。

我也无法使用常规语法

 encoder.encodeObject(medals, forKey: Key.medals)

就像我对使用普通值(例如 [String: Int])的字典数组一样,因为编译器也会抛出错误

arrays swift nscoding
2个回答
11
投票

medals
不是
AnyObject
,因此当您对它进行编码
as? AnyObject
时,您会得到
nil

仅仅因为枚举具有原始字符串值并不意味着您可以自动将其桥接到

[String:String]
。你必须自己做。例如(使用 Airspeed Velocity 版本的
mapValues
):

convenience required init?(coder decoder: NSCoder) {
    self.init()

    if let medalStrings = decoder.decodeObjectForKey(Key.medals) as? [[String: String]] {
        medals = medalStrings.map { $0.mapValues { Medal(rawValue: $0) ?? .Unearned } }
    }

}

func encodeWithCoder(encoder: NSCoder) {
    let medalStrings = medals.map { $0.mapValues { $0.rawValue } }
    encoder.encodeObject(medalStrings, forKey: Key.medals)
}

0
投票

白痴的方法是——令人反感,因为你实例化了两个对象,并且出于其他原因——就是只使用 Codable,然后使用

NSCoding

// MARK: - NSSecureCoding

static var supportsSecureCoding: Bool = true

func encode(with coder: NSCoder) {
    let jsonDecoder = JSONEncoder()
    let coded = try! jsonDecoder.encode(self)

    coder.encode(coded, forKey: "selfAsJSONData")
}

required init?(coder: NSCoder) {
    super.init()
    if let data = coder.decodeObject(of: [NSData.self], forKey: "selfAsJSONData") as? Data {
        let jsonDecoder = JSONDecoder()
        let decodedSelf = try! jsonDecoder.decode(Self.self, from: data)

        // ferry your data over manually ;)
        self.medals = decodedSelf.medals
        // self.prop2 = decodedSelf.prop2
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.