NSKeyedUnarchiver unarchiveTopLevelObjectWithData 已弃用 - 数组加载为 nil,即使它位于存档中

问题描述 投票:0回答:1

自从

NSKeyedUnarchiver.unarchiveTopLevelObjectWithData 

自 macOS 14.0 起已被弃用我现在尝试使用类中设置的 NSSecureCoding 加载旧版 NSCoder 档案并使用:

coder.unarchivedObject(ofClasses classes: [AnyClass], from data: Data) 

加载存档。存档加载并且可以提取大多数类成员。然而,Swift 数组总是输出 nil,尽管

coder.containsValue(forKey:)  

返回真。数组编码为:

var pageUsesClearBackground: Array<Bool> = [true, true, true, true]
coder.encode(pageUsesClearBackground, forKey: "CB_KEY")

使用:

pageUsesClearBackground = coder.decodeObject(forKey: "CB_KEY") as? Array<Bool>

返回一个值为 0 的数组,即使我使用非 NSSecureCode 版本,该数组也会被填充。

pageUsesClearBackground [Bool]  0 values    

我怀疑这与 Swift 中的数组是一个结构并且不符合 NSCoding 有关。奇怪的是它多年来一直在编码和解码它们。知道如何从 NSSecureCoding 之前制作的存档中检索作为数组的类成员吗?

显然,NSSecureCoding 非常安全,您甚至无法取回数据。

arrays swift nscoding nscoder
1个回答
0
投票

这里有一些示例代码,您可以在 Swift Playground 中运行,它允许您取消归档数组:

class Foo: NSObject, NSSecureCoding {
    static var supportsSecureCoding: Bool { true }

    override init() {
        super.init()
    }

    func encode(with coder: NSCoder) {
        // This is based on the array in your question
        var pageUsesClearBackground: Array<Bool> = [true, true, true, true]
        coder.encode(pageUsesClearBackground, forKey: "CB_KEY")
    }

    required init?(coder: NSCoder) {
        // This happily unarchives the [Bool]
        if let pageUsesClearBackground = coder.decodeObject(of: [NSArray.self, NSNumber.self], forKey: "CB_KEY") as? [Bool] {
            print(pageUsesClearBackground) // Shows expected output
        } else {
            print("oops")
        }
    }
}

let foo = Foo()
let data = try NSKeyedArchiver.archivedData(withRootObject: foo, requiringSecureCoding: true)
let bar = try NSKeyedUnarchiver.unarchivedObject(ofClass: Foo.self, from: data)

NSSecureCoding
及相关类都是基于Objective-C的。您需要指定支持
NSCoding
(
NSSecureCoding
) 的类型。因此,在取消存档时,您需要告诉取消存档者您有
NSArray
NSNumber
实例。这就是 Swift
[Bool]
真正转换成的。

© www.soinside.com 2019 - 2024. All rights reserved.