【问题标题】:Writing data to a file with path using NSKeyedArchiver archivedData throws Unrecognized Selector for Swift 4.2使用 NSKeyedArchiver archivedData 将数据写入具有路径的文件会抛出 Unrecognized Selector for Swift 4.2
【发布时间】:2018-11-02 14:38:15
【问题描述】:

我正在尝试使用 NSKeyedArchiver 将 Codable 写入磁盘。

我可以使用已弃用的方法找到有关该主题的所有问题。我找不到任何使用 Swift 4 语法的 SO 问题或教程。

我收到了错误

-[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 

我猜是我的 UsersSession 类中的 try writeData.write(to: fullPath) 行。

在 Swift 4.2 中将数据写入文件的正确方法是什么?

struct UserObject {
    var name : String?
}

extension UserObject  : Codable {

    enum CodingKeys : String, CodingKey {
        case name
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        name = try container.decode(String.self, forKey: .name)

    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(name, forKey: .name)
    }
}

UserSession.swift

class UserSession {
    static let shared = UserSession()

    let fileName = "userdata.dat"

    var user : UserObject?

    lazy var fullPath : URL =  {
        return getDocumentsDirectory().appendingPathComponent(fileName)
    }()

    private init(){
        print("FullPath: \(fullPath)")
        user = UserObject()
        load()
    }

    func save(){
        guard let u = user else { print("invalid user data to save"); return}
        do {
            let writeData = try NSKeyedArchiver.archivedData(withRootObject: u, requiringSecureCoding: false)
            try writeData.write(to: fullPath)
        } catch {
            print("Couldn't write user data file")
        }

    }

    func load() {
        guard  let data = try? Data(contentsOf: fullPath, options: []) else {
            print("No data found at location")
            save()
            return
        }

        guard  let loadedUser = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? UserObject else {
            print("Couldn't read user data file.");
            return
        }

        user = loadedUser

    }

    func getDocumentsDirectory() -> URL {
        return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
    }
}

【问题讨论】:

  • 您混淆了NSCodingCodable。有人重新打开了副本,但它副本。请参阅stackoverflow.com/questions/51812407/…。我的回答描述了协议之间的区别以及如何使用它。将数据写入UserDefaults 或文件是无关紧要的。

标签: swift codable nskeyedarchiver


【解决方案1】:

由于您使用的是 Codable,因此您应该先编码为 Data,然后再编码为 archivedData。代码如下:

   func save(){
        guard let u = user else { print("invalid user data to save"); return}
        do {
            // Encode to Data
            let jsonData = try JSONEncoder().encode(u)
            let writeData = try NSKeyedArchiver.archivedData(withRootObject: jsonData, requiringSecureCoding: false)
            try writeData.write(to: fullPath)
        } catch {
            print("Couldn't write user data file")
        }

    }

    func load() {
        guard  let data = try? Data(contentsOf: fullPath, options: []) else {
            print("No data found at location")
            save()
            return
        }

        guard  let loadedUserData = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? Data else {
            print("Couldn't read user data file.");
            return
        }
        // Decode Data
        user = try? JSONDecoder().decode(UserObject.self, from: loadedUserData)

    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-01
    • 2017-05-22
    • 2020-09-17
    • 2013-03-08
    • 2019-06-10
    • 1970-01-01
    相关资源
    最近更新 更多