Как добавить новый ключ и значение в существующие архивы с ключами, используя NSCoding - PullRequest
0 голосов
/ 08 октября 2018

Попытка добавить новый ключ «пароль».Существующая версия приложения имеет эти существующие ключи «имя», «ip», «порт» и имеет сохраненные значения.При добавлении нового ключа «пароль» приложение не может прочитать существующие данные и отображает эту ошибку «Невозможно декодировать имя для системного объекта».который из следующего кода:

guard let password = aDecoder.decodeObject(forKey: PropertyKey.password) as? String else {
            os_log("Unable to decode the name for a System object.", log: OSLog.default, type: .debug)
            return nil
        }

Мой вопрос заключается в том, как добавить новый ключ «пароль», назначив значение по умолчанию «123456» для всех существующих ключей архива (данных / объектов), и не уничтожая существующие данные,

e.g.
name = "System01", ip = "10.0.0.3", port = "3535", password = "123456" 
name = "System02", ip = "10.0.0.4", port = "3535", password = "123456" 

==================================

import UIKit
import os.log

class System: NSObject, NSCoding {


    //MARK: Properties

    var name: String
    var ip: String
    var port: String
    var password: String. // Added this new key

    //MARK: Archiving Paths

    static let DocumentsDirectory = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first!
    static let ArchiveURL = DocumentsDirectory.appendingPathComponent("systems")

    //MARK: Types

    struct PropertyKey {
        static let name = "name"
        static let ip = "ip"
        static let port = "port"
        static let password = "password"  // Added this new key
    }

    //MARK: Initialization

    init(name: String, ip: String, port: String, password: String) {

        // Initialize stored properties.
        self.name = name
        self.ip = ip
        self.port = port
        self.password = password  // Added this new key
    }

    //MARK: NSCoding

    func encode(with aCoder: NSCoder) {
        aCoder.encode(name, forKey: PropertyKey.name)
        aCoder.encode(ip, forKey: PropertyKey.ip)
        aCoder.encode(port, forKey: PropertyKey.port)
        aCoder.encode(password, forKey: PropertyKey.password)  // Added this new key
    }

    required convenience init?(coder aDecoder: NSCoder) {

        // The name is required. If we cannot decode a name string, the initializer should fail.
        guard let name = aDecoder.decodeObject(forKey: PropertyKey.name) as? String else {
            os_log("Unable to decode the name for a System object.", log: OSLog.default, type: .debug)
            return nil
        }
        guard let ip = aDecoder.decodeObject(forKey: PropertyKey.ip) as? String else {
            os_log("Unable to decode the name for a System object.", log: OSLog.default, type: .debug)
            return nil
        }
        guard let port = aDecoder.decodeObject(forKey: PropertyKey.port) as? String else {
            os_log("Unable to decode the name for a System object.", log: OSLog.default, type: .debug)
            return nil
        }
        guard let password = aDecoder.decodeObject(forKey: PropertyKey.password) as? String else {
            os_log("Unable to decode the name for a System object.", log: OSLog.default, type: .debug)
            return nil
        }  // Added this new key

        // Must call designated initializer.
        self.init(name: name, ip: ip, port: port, password: password)

    }
}

Ответы [ 2 ]

0 голосов
/ 08 октября 2018

Если вы хотите поддерживать текущее приложение без crash , вам нужно создать новый класс, унаследованный от вашего класса "System".Также вы должны обрабатывать как текущий сценарий, так и будущие сценарии, используя соответствующие проверки для надлежащего кодирования и декодирования объектов.

Конечно, вы можете следовать коду, упомянутому @Gereon, но в случае, если вы хотите добавить больше значений ключа, лучше расширить класс.

0 голосов
/ 08 октября 2018

Ваш код должен работать без сбоев в случае отсутствия пароля.Замените деталь guard let password ... чем-то вроде этого:

let decodedPassword = aDecoder.decodeObject(forKey: PropertyKey.password) as? String
let password = decodedPassword ?? "123456"

, а затем выполните

self.init(name: name, ip: ip, port: port, password: password)
...