簡體   English   中英

NSKeyedArchiver不歸檔我的Codable類

[英]NSKeyedArchiver does not archive my Codable class

這是我的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)
    }

這會在歸檔過程中出錯錯誤截圖

PS:我以這種方式收到的filePath:

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以及其他支持的類型,但不適用於我的類型。 怎么了?

盡管@ 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錯誤而不是崩潰。)

錯誤消息告訴您SensorOutput需要從NSObject派生。

但是,根本問題是您使用的NSKeyedArchiver錯誤。 您正在調用archiveRootObject ,就像這種類型采用NSCoding一樣。 它沒有。 它采用Codable。 如果您打算使用此類型為Codable的事實,則調用NSKeyedArchiver encodeEncodable(_:forKey:)進行編碼,並調用decodeDecodable(_:forKey:)進行解碼。

你以錯誤的方式使用它。 它采用Codable協議而非NSCoding協議。 (正如@matt指出的那樣)

你可以這樣解決它:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM