How to replace NSKeyedUnarchiver.unarchiveTopLevelObjectWithData with unarchivedObject when data is a Dictionary

huangapple go评论143阅读模式
英文:

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.selfNSNumber.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]"
)}

huangapple
  • 本文由 发表于 2023年3月4日 05:31:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/75632048.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定