NSKeyedArchiver: приведение данных, возвращающих ноль - Swift - PullRequest
0 голосов
/ 12 февраля 2019

Хорошо, мы исследовали несколько подобных тем здесь, сделали все, как было предложено, но мое вычисленное свойство «previousUserData» возвращает мне ноль, когда я пытаюсь привести декодированный объект к моему типу.Что не так?

@objc class PreviousUserData: NSObject, NSCoding {

var name: String
var phone: String
var email: String

func encode(with aCoder: NSCoder) {
    aCoder.encode(name, forKey: "name")
    aCoder.encode(phone, forKey: "phone")
    aCoder.encode(email, forKey: "email")
}

required convenience init?(coder aDecoder: NSCoder) {
    guard
        let name = aDecoder.decodeObject(forKey: "name") as? String,
        let phone = aDecoder.decodeObject(forKey: "phone") as? String,
        let email = aDecoder.decodeObject(forKey: "email") as? String
        else {
            return nil
    }
    self.init(name: name, phone: phone, email: email)
}

init(name: String, phone: String, email: String) {
    self.name = name
    self.phone = phone
    self.email = email
}
}

unarchived возвращает мне ноль, но данные для ключа userdata существуют

    var previousUserData: PreviousUserData? {
    get {
        if let object = UserDefaults.standard.object(forKey: "userdata") as? Data {
            let unarchived = NSKeyedUnarchiver.unarchiveObject(with: object) as? PreviousUserData
            return unarchived
        }
        return nil
    }
    set {
        let encodedData: Data = NSKeyedArchiver.archivedData(withRootObject: previousUserData as Any)
        UserDefaults.standard.setValue(encodedData, forKey: "userdata")
    }
    }

1 Ответ

0 голосов
/ 12 февраля 2019

На самом деле вы не можете получить действительные данные, потому что установщик неверен.Вы должны сохранить newValue вместо previousUserData.

Это слегка оптимизированная версия

var previousUserData: PreviousUserData? {
    get {
        guard let data = UserDefaults.standard.data(forKey: "userdata") else { return nil }
        return NSKeyedUnarchiver.unarchiveObject(with: data) as? PreviousUserData
    }
    set {
        guard let newValue = newValue else { return }
        let encodedData = NSKeyedArchiver.archivedData(withRootObject: newValue)
        UserDefaults.standard.set(encodedData, forKey: "userdata")
    }
}

NSCoding довольно тяжелая.В этом случае я бы рекомендовал использовать Codable для сериализации данных в виде JSON или списка свойств.Он избавляется от @objc, class и NSObject и уменьшает весь код до

struct PreviousUserData : Codable {
    var name: String
    var phone: String
    var email: String
}

var previousUserData: PreviousUserData? {
    get {
        guard let data = UserDefaults.standard.data(forKey: "userdata") else { return nil }
        return try? JSONDecoder().decode(PreviousUserData.self, from: data)
    }
    set {
        guard let newValue = newValue, let encodedData = try? JSONEncoder().encode(newValue) else { return }
        UserDefaults.standard.set(encodedData, forKey: "userdata")
    }
}
...