顶级 Bool 编码为数字 属性 列表片段。属性列表编码器
Top-level Bool encoded as number property list fragment. PropertyListEncoder
我有这个通用函数可以保存在 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)
这是我得到的错误。我知道还有另一种保存布尔值的方法,但我想知道为什么它不能像这样工作?
Thread 1: Fatal error: 'try!' expression unexpectedly raised an error:
Swift.EncodingError.invalidValue(false,
Swift.EncodingError.Context(codingPath: [], debugDescription:
"Top-level Bool encoded as number property list fragment.",
underlyingError: nil))
谢谢!
A PropertyListEncoder
编码为“属性 列表”,这始终是一个
数组或字典,比较 PropertyListSerialization.
因此
let data = try PropertyListEncoder().encode(myType)
如果 myType
是一个 Bool
(或任何不是数组的东西)则失败
或字典)。
属性列表中的可能对象也受到限制,它们只能是实例
NSData
、NSString
、NSArray
、NSDictionary
、NSDate
或 NSNumber
– 或 Swift 类型
桥接到其中一种基础类型。
正如@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
您无需对布尔值进行编码即可保存到 UserDefaults 中。您可以通过调用
直接将布尔值保存到 UserDefaults 中
let myValue: Bool = false
UserDefaults.standard.set(myValue, forKey: "key")
查看 Apple 文档:UserDefaults.set(_:forKey:)。
其实Float、Double、Integer、Bool和URL类型都不需要编码,直接保存到UserDefaults即可。
我看到您有一个函数接受 Codable 类型,对其进行编码,然后将其保存到 UserDefaults。正如 Martin R 指出的那样,您必须修改该函数并检查传递的对象是否可以直接保存到 UserDefaults 而无需编码。它不一定很漂亮,但像这样的东西可以工作:
switch objectToSave {
case let aFloatType as Float:
UserDefaults.standard.set(aFloatType, forKey: "key")
case let aDoubleType as Double:
UserDefaults.standard.set(aDoubleType, forKey: "key")
case let anIntegerType as Int:
UserDefaults.standard.set(anIntegerType, forKey: "key")
case let aBoolType as Bool:
UserDefaults.standard.set(aBoolType, forKey: "key")
case let aURLType as URL:
UserDefaults.standard.set(aURLType, forKey: "key")
default:
//encode the object as a PropertyList and then save it to UserDefaults
do {
let data = try PropertyListEncoder().encode(objectToSave)
UserDefaults.standard.set(data, forKey: key)
} catch let error {
//the object you passed cannot be encoded as a PropertyList
//possibly because the object cannot be represented as
//NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary - or equivalent Swift types
//also contents of NSArray and NSDictionary have to be one of the types above
print("Save Failed: \(error)")
//perform additional error handling
}
}
我有这个通用函数可以保存在 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)
这是我得到的错误。我知道还有另一种保存布尔值的方法,但我想知道为什么它不能像这样工作?
Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: Swift.EncodingError.invalidValue(false, Swift.EncodingError.Context(codingPath: [], debugDescription: "Top-level Bool encoded as number property list fragment.", underlyingError: nil))
谢谢!
A PropertyListEncoder
编码为“属性 列表”,这始终是一个
数组或字典,比较 PropertyListSerialization.
因此
let data = try PropertyListEncoder().encode(myType)
如果 myType
是一个 Bool
(或任何不是数组的东西)则失败
或字典)。
属性列表中的可能对象也受到限制,它们只能是实例
NSData
、NSString
、NSArray
、NSDictionary
、NSDate
或 NSNumber
– 或 Swift 类型
桥接到其中一种基础类型。
正如@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
您无需对布尔值进行编码即可保存到 UserDefaults 中。您可以通过调用
直接将布尔值保存到 UserDefaults 中 let myValue: Bool = false
UserDefaults.standard.set(myValue, forKey: "key")
查看 Apple 文档:UserDefaults.set(_:forKey:)。
其实Float、Double、Integer、Bool和URL类型都不需要编码,直接保存到UserDefaults即可。
我看到您有一个函数接受 Codable 类型,对其进行编码,然后将其保存到 UserDefaults。正如 Martin R 指出的那样,您必须修改该函数并检查传递的对象是否可以直接保存到 UserDefaults 而无需编码。它不一定很漂亮,但像这样的东西可以工作:
switch objectToSave {
case let aFloatType as Float:
UserDefaults.standard.set(aFloatType, forKey: "key")
case let aDoubleType as Double:
UserDefaults.standard.set(aDoubleType, forKey: "key")
case let anIntegerType as Int:
UserDefaults.standard.set(anIntegerType, forKey: "key")
case let aBoolType as Bool:
UserDefaults.standard.set(aBoolType, forKey: "key")
case let aURLType as URL:
UserDefaults.standard.set(aURLType, forKey: "key")
default:
//encode the object as a PropertyList and then save it to UserDefaults
do {
let data = try PropertyListEncoder().encode(objectToSave)
UserDefaults.standard.set(data, forKey: key)
} catch let error {
//the object you passed cannot be encoded as a PropertyList
//possibly because the object cannot be represented as
//NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary - or equivalent Swift types
//also contents of NSArray and NSDictionary have to be one of the types above
print("Save Failed: \(error)")
//perform additional error handling
}
}