我有一个函数,用于将确认NSCoding
的原语和对象保存到UserDefaults
。
func set(_ value: Any?, forKey key: String) {
if let value = value {
if (value is NSCoding) {
let encodedValue = NSKeyedArchiver.archivedData(withRootObject: value)
UserDefaults.standard.set(encodedValue, forKey: key)
} else {
print("Storage: failed to save value for key \(key). Value must confirm to NSCoding protocol")
}
} else {
UserDefaults.standard.removeObject(forKey: key)
}
}
我想摆脱函数内部的一致性检查。因此该函数必须仅接受NSCoding
值。
我尝试将函数的签名更改为此:
func set(_ value: NSCoding?, forKey key: String)
这:
func set<T: Any>(_ value: T?, forKey key: String) where T: NSCoding
但是,在每个函数调用中都会出现编译错误。
在第一种情况下,我得到:
参数类型“ ***”不符合预期的类型“ NSCoding?”
第二个:
无法将类型“ ***”的值转换为预期的参数类型“ _?”
我应该进行哪些更改才能使其正常工作?
答案 0 :(得分:1)
方法声明本身似乎没有问题
func set<T: Any>(_ value: T?, forKey key: String) where T: NSCoding {
if let value = value {
let encodedValue = NSKeyedArchiver.archivedData(withRootObject: value)
UserDefaults.standard.set(encodedValue, forKey: key)
} else {
UserDefaults.standard.removeObject(forKey: key)
}
}
但是编译错误指出您传递给该函数的值可能与NSCoding
使用
调用上述函数的示例self.set("abcd", forKey: "test")
出现错误
无法将类型为“字符串”的值转换为预期的参数类型为“ _?”
另一方面称它为
self.set(NSString(string: "abcd"), forKey: "test")
工作正常。因此,请确保您传递正确的参数:)
编辑1:
基于OP的评论,使用Int
let test: Int = 100
self.set(test, forKey: "test")
导致同样的错误,但是将其装箱到NSNumber
let test: Int = 100
self.set(NSNumber(value: test), forKey: "test")
编辑2:
回答OP的评论
但是如果我的原件(值是NSCoding)签入,为什么要通过字符串值 功能?
let a: Any = "abcd"
if a is NSCoding {
debugPrint("am here")
}
那是因为你的任何经过NSCoding
检查,并在你的情况,无论什么样的价值传递给函数,你键入它转换为Any
和Any
通过检查:) < / p>
因此可以在您的第一种方法中使用,但无法使用泛型:) 希望对您有帮助
答案 1 :(得分:1)
也许您可以一起跳过NSCoding
?
func set(_ value: Any?, forKey key: String) throws {
if let value = value {
let encodedValue = try NSKeyedArchiver.archivedData(withRootObject: value, requiringSecureCoding: true)
UserDefaults.standard.set(encodedValue, forKey: key)
} else {
UserDefaults.standard.removeObject(forKey: key)
}
}
(请注意,我改用了不推荐使用的方法,但随时可以改回来)
示例
do {
try set("abc", forKey: "k1")
} catch {
print(error)
}