我已经编写了这个函数来保存我的钥匙链存储中的可编码对象。我将一个字符串API密钥传递给这个函数作为值,在13+ iOS版本中,它工作得非常好。
class StoreManager {
public static func save<T: Codable>(_ value: T, forKey key: String) {
guard let data = try? JSONEncoder().encode(value) else {
return
}
try? keychain.set(data, key: key)
}
}
let dummyApiKey = "1234567=8+90"
StoreManager().save(dummyApiKey, forKey: "id")
在iOS 12中,不知何故,String值不能被编码,并且guard语句变成了return。有谁知道iOS 12有什么不同让它无法编码吗?
如果你不能自己调试,永远不要使用try?
。有了更多的经验,我想说我们倾向于不使用try?
,但有时我们会这样做。但是当我们写try?
时,我们能够找到一个可能的问题,即调试如果需要的话。
让我们做一个适当的尝试,用do/catch:
do {
let data = try JSONEncoder().encode(value)
print(data)
} catch {
print("Error: (error)")
}
并读取输出。另外,不要输出error.localizedDescription
,因为它更适合用户而不是开发人员,而要输出error
。
输出为:
Error: invalidValue("1234567=8+90",
Swift.EncodingError.Context(codingPath: [],
debugDescription: "Top-level String encoded as string JSON fragment.",
underlyingError: nil))
也就是说:JSON 99%的情况下是Dictionary
或Array
,在可编码的措辞中,它是一个可编码的结构体,带有它的属性或它的数组。但是,一些JSON引用允许简单的String
是JSON有效的。
我猜在iOS13+中JSONEncoder
是允许的(见相关问题)
在iOS中,它是fragment
。该选项适用于较旧的JSONSerialization
,但不适用于JSONEncoder
。
let data = JSONSerialization.data(withJSONObject: value, options: [.fragmentsAllowed])
现在,您可以使用@available(iOS 13, *)
调用JSONEncoder
或JSONSerialization
:
if #available(iOS 13.0, *) {
//Do the JSONEncoder thing
} else {
//Do the JSONSerialization Thing
}
免责声明:try?
的开头是MY OWN的另一个答案的复制/粘贴。所以没有抄袭。