swift NSCoder:如何编码/解码[数据]数组

fhity93d  于 2023-06-21  发布在  Swift
关注(0)|答案(1)|浏览(100)

我在NSCoder协议中编码/解码一组数据(基本上是文件书签)时遇到了问题。
这就是我想做的

class ClosedFiles: NSCoder {
    static var supportsSecureCoding = true
    let bookmarks: [Data]
    init?(with coder: NSCoder) {
        if let bm = coder.decodeObject() as? [Data] {
            bookmarks = bm
        } else {
            return nil
        }
    }
    init(bookmarks: [Data]) {
        self.bookmarks = bookmarks
    }
    
    func encode(with coder: NSCoder) {
        coder.encodeRootObject(bookmarks)
    }
}

我在我的app delegate中编码了这个对象:

func application(_ app: NSApplication, willEncodeRestorableState coder: NSCoder) {
    coder.encodeRootObject(ClosedFiles(bookmarks: closedFiles))
}

这会在运行时抛出错误:
忽略异常:此解码器将仅解码采用NSSecureCoding的类。类“_TtCC7MyApp11AppDelegate11ClosedFiles”不采用它。
我遵循apple's doc以符合NSSecure,但它似乎不起作用。我尝试了几种方法,但似乎都不起作用:coder.encode()、coder.encodeConditionalObject和我找到的其他东西。
你觉得我哪里做错了吗?

sd2nnvve

sd2nnvve1#

您需要对类进行大量更改以支持NSCoding(实际上是NSSecureCoding)。

  • 类必须扩展NSObject
  • 您的类需要符合NSSecureCoding
  • 您需要init(coder:)初始化器的正确签名
  • supportsSecureCoding属性必须是静态的
  • 两个NSCoding方法的实现需要正确编写以支持安全编码。

这是您的类,其中包含所有更改。

class ClosedFiles: NSObject, NSSecureCoding {
    let bookmarks: [Data]

    required init?(coder: NSCoder) {
        if let bm = coder.decodeArrayOfObjects(ofClass: NSData.self, forKey: "bookmarks") as? [Data] {
            bookmarks = bm
        } else {
            return nil
        }
    }

    init(bookmarks: [Data]) {
        self.bookmarks = bookmarks
    }

    func encode(with coder: NSCoder) {
        coder.encode(bookmarks as [NSData], forKey: "bookmarks")
    }

    static var supportsSecureCoding: Bool {
        return true
    }
}

我使用以下代码在Playground中测试了这些更改:

do {
    let closed = ClosedFiles(bookmarks: [ "Hello".data(using: .utf8)!, "There".data(using: .utf8)! ])
    let data = try NSKeyedArchiver.archivedData(withRootObject: closed, requiringSecureCoding: true)
    let dupe = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [ClosedFiles.self, NSArray.self, NSData.self], from: data) as! ClosedFiles
    let str1 = String(data: dupe.bookmarks[0], encoding: .utf8)!
    print(str1)
} catch {
    print(error)
}

这将返回预期的结果。

相关问题