*** Bool 编码为数字属性列表片段。属性列表编码器

Posted

技术标签:

【中文标题】*** Bool 编码为数字属性列表片段。属性列表编码器【英文标题】:Top-level Bool encoded as number property list fragment. PropertyListEncoder 【发布时间】:2018-11-06 17:53:35 【问题描述】:

我有这个通用函数可以保存在 NSUserDefaults 中,通常可以使用,但现在我想保存一个布尔值,但出现错误。我找不到任何东西,我不明白为什么它不起作用。

extension UserDefaults 
    func saveUserDefaults<T: Codable>(withKey key: String, myType: T) throws
        do 
            let data = try PropertyListEncoder().encode(myType)
            UserDefaults.standard.set(data, forKey: key)
            print("Saved for Key:", key)
         catch let error 

            print("Save Failed")
            throw error
        
    

我这样称呼它:

try! UserDefaults().saveUserDefaults(withKey: "String", myType: false)

这是我得到的错误。我知道还有另一种保存布尔值的方法,但我想知道为什么它不能这样工作?

线程 1:致命错误:“尝试!”表达式意外引发错误: Swift.EncodingError.invalidValue(假, Swift.EncodingError.Context(codingPath: [], debugDescription: "编码为数字属性列表片段的*** Bool。", 底层错误:无))

谢谢!

【问题讨论】:

属性列表总是需要字典或数组作为***对象,比较developer.apple.com/documentation/foundation/…。 这不是我设置密钥的原因吗? false 是布尔值,而不是字典。它也会因整数或字符串而失败。 【参考方案1】:

正如@Martin 所说,PropertyListEncoder 仅支持顶层的属性列表,而不支持像 NSNumber 这样的属性列表的单个片段。 一个非常简单(虽然不是很优雅)的解决方法是将任何对象包装到数组中:

let data = try PropertyListEncoder().encode([myType])
UserDefaults.standard.set(data, forKey: key)

并将其解码为:

let arr = try  PropertyListDecoder().decode([T].self, from: data)
return arr.first

见https://www.marisibrothers.com/2018/07/workaround-for-serializing-codable-fragments.html

【讨论】:

这个真的很有用!【参考方案2】:

PropertyListEncoder 编码为“属性列表”,这始终是 数组或字典,比较PropertyListSerialization。

因此

let data = try PropertyListEncoder().encode(myType)

如果myTypeBool(或任何不是数组的东西)则失败 或字典)。

属性列表中的可能对象也受到限制,它们只能是 NSDataNSStringNSArrayNSDictionaryNSDateNSNumber - 或 Swift 类型 桥接到这些 Foundation 类型之一。

【讨论】:

【参考方案3】:

您无需编码布尔值即可保存到 UserDefaults。您可以通过调用直接将布尔值保存到 UserDefaults 中

    let myValue: Bool = false
    UserDefaults.standard.set(myValue, forKey: "key")

请参阅 Apple 文档:UserDefaults.set(_:forKey:)。

我看到您有一个采用 Codable 类型的函数,对其进行编码,然后将其保存到 UserDefaults。正如 Martin R 指出的那样,您将不得不修改该函数并检查是否可以将传递的对象直接保存到 UserDefaults 而无需编码。

【讨论】:

以上是关于*** Bool 编码为数字属性列表片段。属性列表编码器的主要内容,如果未能解决你的问题,请参考以下文章

C# linq:在同一属性字段的列表中检查多个条件

CSS 列表

在 Objective-C 中获取对象属性列表

VB大神赐教!怎么让下拉列表combobox只能选择不能写入其他值?

Operator '||' cannot be applied to operands of type 'bool?' and 'bool?'(代码片段

Operator '||' cannot be applied to operands of type 'bool?' and 'bool?'(代码片段