首页 > 解决方案 > 将 Codable 保存到 UserDefaults 并匹配 NSCoding 的外观

问题描述

我有一个支持该协议的struct调用。由于它是一个结构,它不能支持协议。我想将这些s 的数组保存到. 我有没有任何问题的代码。StationCodableNSCodingStationUserDefaults

func updateRecentStations(stations: [Station]) {
    let encoder = PropertyListEncoder()
    encoder.outputFormat = .xml
    let data = try! encoder.encode(stationsArray)
    UserDefaults.standard.set(data, forKey: "RecentStations")
}

func readRecentStations() -> [Station] {
    if let data = UserDefaults.standard.object(forKey: "RecentStations") as? Data {
        let stations: [Station] = try! PropertyListDecoder().decode( [Station].self, from: data)
        return stations
    }
}

这些都有效。往返没有问题。但是如果我在Xcode中检查<<app>>.plist,或者调用print(Array(UserDefaults.standard.dictionaryRepresentation()))显示的数据是难以辨认的。所写的Data看起来像是以十六进制格式存储的。也就是说,如果我在文本编辑器中打开 <<app>>.plist,我可以在其中看到 xml,但 .plist 并不意味着以这种方式阅读。

UserDefaults似乎不支持将 plist 写入 .plist 。一切正常,但因为 plist 编辑器无法阅读我写的内容,我觉得我做事的方式不正确。

有没有一种方法可以支持一个Codable被写入的UserDefaults对象,使其在其中以人类可读的方式保持其结构?需要明确的是,我正在寻找一种复制NSCoding将添加到NSUserDefaults层次结构的方式的方式。

标签: iosswiftnsuserdefaultsuserdefaults

解决方案


您存储DataUserDefaults. 这将被编码为 base64 字符串,这就是为什么它不是人类可读的。

由于您正在编码为 XML 格式,因此结果Data实际上将是表示 XML 的字符串的数据。所以创建一个Stringfrom data。然后将该字符串存储在UserDefaults. UserDefaults然后在查看plist 文件时 XML 将是可读的。

注意:以下内容未经测试。可能有错别字。

func updateRecentStations(stations: [Station]) {
    let encoder = PropertyListEncoder()
    encoder.outputFormat = .xml
    let data = try! encoder.encode(stationsArray)
    let xml = String(data: data, encoding: .utf8)!
    UserDefaults.standard.set(xml, forKey: "RecentStations")
}

func readRecentStations() -> [Station] {
    if let xml = UserDefaults.standard.object(forKey: "RecentStations") as? String {
        let data = xml.data(using: .utf8)!
        let stations: [Station] = try! PropertyListDecoder().decode( [Station].self, from: data)
        return stations
    }
}

推荐阅读