【问题标题】:NSKeyedArchiver does not archive my Codable classNSKeyedArchiver 不归档我的 Codable 类
【发布时间】:2018-10-01 18:23:56
【问题描述】:

这是我的 Codable 类:

class SensorOutput: Codable {

    var timeStamp: Date?

    var gyroX: Double?
    var gyroY: Double?
    var gyroZ: Double?

    var accX: Double?
    var accY: Double?
    var accZ: Double?

    var magX: Double?
    var magY: Double?
    var magZ: Double?

    init() {}
}

这里我尝试将该类的对象写入和读取到文件中:

    let myData = SensorOutput()
    myData.timeStamp = Date()
    myData.gyroX = 0.0
    myData.gyroY = 0.0
    myData.gyroZ = 0.0
    myData.accX = 0.0
    myData.accY = 0.0
    myData.accZ = 0.0
    myData.magX = 0.0
    myData.magY = 0.0
    myData.magZ = 0.0

    NSKeyedArchiver.archiveRootObject(myData, toFile: filePath)

    if let Data = NSKeyedUnarchiver.unarchiveObject(withFile: filePath) as? SensorOutput {
        print (Data)
    }

这会在归档过程中出现错误: Error screenshot

PS:我以这种方式接收的文件路径:

var filePath: String {
    //1 - manager lets you examine contents of a files and folders in your app; creates a directory to where we are saving it
    let manager = FileManager.default
    //2 - this returns an array of urls from our documentDirectory and we take the first path
    let url = manager.urls(for: .documentDirectory, in: .userDomainMask).first
    print("this is the url path in the documentDirectory \(String(describing: url))")
    //3 - creates a new path component and creates a new file called "Data" which is where we will store our Data array.
    return (url!.appendingPathComponent("Data").path)
}

读/写适用于 Int 或 Double 以及其他支持的类型,但不适用于我的类型。怎么了?

【问题讨论】:

    标签: ios swift4 nskeyedarchiver codable


    【解决方案1】:

    虽然@matt 的答案包含解决您的问题的基本信息,但如果您是 Swift 和 iOS 编程新手,如何应用这些信息可能并不明显。

    您尝试使用NSKeyedArchiver.archiveRootObject(_:toFile:),这是一个类方法,因此您不必创建NSKeyedArchiver 的实例。由于encodeEncodable(_:forKey:)是实例方法,不是类方法,所以需要创建NSKeyedArchiver的实例才能使用。您还需要为归档程序创建一个NSMutableData 以将字节附加到,并且您必须在编码对象后调用finishEncoding

        let sensorOutput = SensorOutput()
        sensorOutput.timeStamp = Date()
    
        let mutableData = NSMutableData()
        let archiver = NSKeyedArchiver(forWritingWith: mutableData)
        try! archiver.encodeEncodable(sensorOutput, forKey: NSKeyedArchiveRootObjectKey)
        archiver.finishEncoding()
    
        // You can now write mutableData to a file or send it to your server
        // or whatever.
    

    同样,您尝试使用NSKeyedUnarchiver.unarchiveObject(withFile:),这是一个类方法,但您需要使用decodeDecodable(_:forKey:)decodeTopLevelDecodable(_:forKey:),它们是实例方法。所以你需要读入归档数据并使用它来创建NSKeyedUnarchiver的实例。

    // Read in the data from a file or your server or whatever.
    // I'll just make an immutable copy of the archived data for this example.
    let data = mutableData.copy() as! Data
    
    let unarchiver = NSKeyedUnarchiver(forReadingWith: data)
    do {
        if let sensorOutputCopy = try unarchiver.decodeTopLevelDecodable(SensorOutput.self, forKey: NSKeyedArchiveRootObjectKey) {
            print("deserialized sensor output: \(sensorOutputCopy)")
        }
    } catch {
        print("unarchiving failure: \(error)")
    }
    

    (我更喜欢 decodeTopLevelDecodable 方法而不是 decodeDecodable,因为如果存档损坏,它会引发 Swift 错误而不是崩溃。)

    【讨论】:

    • 感谢您的详细回答,一切正常。但是如何获取 NSMutableData 的 URL 或如何使用 transferFile(_:metadata:) 将保存的文件从 Apple Watch 发送到 iPhone?
    • 您可以使用write(toFile:atomically:)write(toFile:options:)write(to:atomically:)write(to:options:) 方法之一将NSMutableData 写入文件。 (它从NSData 继承这些方法)。
    【解决方案2】:

    错误信息告诉你SensorOutput需要从NSObject派生。

    但是,根本问题是您使用 NSKeyedArchiver 错误。你打电话给archiveRootObject,就好像这种类型采用了NSCoding。它没有。它采用 Codable。如果你打算使用这种类型是 Codable 的事实,你调用 NSKeyedArchiver encodeEncodable(_:forKey:) 编码和 NSKeyedUnarchiver decodeDecodable(_:forKey:) 解码。

    【讨论】:

      【解决方案3】:

      你用错了。它采用Codable 协议而不是NSCoding 之一。 (正如@matt 指出的那样)

      你可以这样解决:

      let myData = SensorOutput()
      let data = try! PropertyListEncoder().encode(myData)
      NSKeyedArchiver.archivedData(withRootObject: data)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多