-1

Trying to add a new key "password". Existing version of the app has these existing keys "name", "ip", "port", and has stored values. When the new key "password" is added, the app fails to read the existing data, and shows this error "Unable to decode the name for a System object." which from following code:

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
        }

My question is how to add new key "password" assign a default value of "123456" to all existing keyed archive(data/objects), and without destroying the existing data.

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)

    }
}
Kevin W
  • 31
  • 4

2 Answers2

4

Your code needs to not fail in the case that no password is present. Replace the guard let password ... part with something like this:

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

and then do

self.init(name: name, ip: ip, port: port, password: password)
Gereon
  • 17,258
  • 4
  • 42
  • 73
0

If you want to support current application without crash, you have to create a new class inherited from your class "System". Also you have to handle both current scenario as well as future scenarios by using appropriate checks to encode & decode the objects appropriately.

Of course, you can follow the code as mentioned by @Gereon, but in case if you want to add more key-values, its better to extend the class.

Satyam
  • 15,493
  • 31
  • 131
  • 244