英文:
How to replace NSKeyedUnarchiver.unarchiveTopLevelObjectWithData with unarchivedObject when data is a Dictionary
问题
iOS 16.4 废弃了 unarchiveTopLevelObjectWithData(_:)
方法,应该替换为 unarchivedObject(ofClass:from:)
。
当你对一个 Swift 字典([String: Any]
)进行归档时,如何使用新的 API 进行解档呢?
使用NSKeyedUnarchiver.unarchivedObject(ofClass: [String: Any].self, from: data)
会导致构建时错误:
静态方法 'unarchivedObject(ofClass:from:)' 要求 '[String: Any]' 符合 'NSCoding'
// 从字典创建数据
let dictionary: [String: Any] = ["Text": "Hello", "Number": 1, "Array": ["Hello", "World"]]
let data = try! NSKeyedArchiver.archivedData(withRootObject: dictionary, requiringSecureCoding: true)
// 然后从数据中获取字典
let dictionary = try? NSKeyedUnarchiver.unarchivedObject(ofClass: [String: Any].self, from: data) //抱歉,无法完成
英文:
iOS 16.4 deprecates unarchiveTopLevelObjectWithData(_:)
and should be replaced with unarchivedObject(ofClass:from:)
.
When you archived a Swift Dictionary like [String: Any]
, how do you use the newer API to unarchive it?
NSKeyedUnarchiver.unarchivedObject(ofClass: [String: Any].self, from: data)
results in a build time error:
> Static method 'unarchivedObject(ofClass:from:)' requires that '[String : Any]' conform to 'NSCoding'
//create the data from dictionary
let dictionary: [String: Any] = ["Text": "Hello", "Number": 1, "Array": ["Hello", "World"]]
let data = try! NSKeyedArchiver.archivedData(withRootObject: dictionary, requiringSecureCoding: true)
//and later get the dictionary from the data
let dictionary = try? NSKeyedUnarchiver.unarchivedObject(ofClass: [String: Any].self, from: data) //sorry no can do
答案1
得分: 8
由于Swift类型为[String: Any]
的字典不符合NSCoding
协议,所以您需要返回到使用NSDictionary
。由于您还在使用安全编码,您还需要列出字典中可能包含的所有类型。
您需要使用unarchivedObject(ofClasses:from:)
方法,以便您可以列出所有的类。
let dictionary = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSDictionary.self, NSArray.self], from: data) as? NSDictionary
您可能还需要将NSString.self
和NSNumber.self
添加到类列表中。持续添加在错误消息中出现的类,直到代码正常工作。
英文:
Since the Swift dictionary of type [String: Any]
doesn't conform to NSCoding
, you need to drop back to using NSDictionary
. Since you are also using secure coding, you also need to list all types that can be in the dictionary.
You will need to use the unarchivedObject(ofClasses:from:)
method so you can list all of the classes.
let dictionary = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSDictionary.self, NSArray.self], from: data) as? NSDictionary
You may also end up needing to add NSString.self
and NSNumber.self
to the list of classes. Keep adding the classes that appear in the error message until it works.
答案2
得分: -1
你可以使用这个虚拟对象:[NSObject.self]
,而不是[NSDictionary.self, NSArray.self ...... ]
。
通过这样做,你涵盖了所有的 NS 案例。
这对我来说有效,尽管出现了紫色的消息(Apple 总是保守的。不坏,但...
-[NSKeyedUnarchiver validateAllowedClass:forKey:]: NSSecureCoding 允许的类列表包括 [NSObject class],这绕过了安全性,允许隐式解码任何 Objective-C 类。在解码期间考虑减小允许类的范围,只列出你期望解码的类,或者使用比 NSObject 更具体的基类。这将在将来变成一个错误。允许的类列表: {
"'NSObject' (0x219ef2d98) [/usr/lib]"
)}
英文:
You can use this dummy object: [NSObject.self]
instead of [NSDictionary.self, NSArray.self ...... ]
.
With this, you cover all NS cases.
It worked for me, although purple message appears (Apple always on the safe side. Not bad, but...
>-[NSKeyedUnarchiver validateAllowedClass:forKey:]: NSSecureCoding allowed classes list contains [NSObject class], which bypasses security by allowing any Objective-C class to be implicitly decoded. Consider reducing the scope of allowed classes during decoding by listing only the classes you expect to decode, or a more specific base class than NSObject. This will become an error in the future. Allowed class list: {(
"'NSObject' (0x219ef2d98) [/usr/lib]"
)}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论