User Defaults not saving dictionary contents in swift 3

邮差的信 提交于 2019-12-11 06:08:10

问题


I am trying to add a key and a value to a dictionary then add this dictionary the user defaults and read back into a dictionary object. I have two questions that I would really appreciate any help in,

1) why is the dictionary being read from user defaults empty? Since I added a key and a value to the dictionary shouldn't those be saved to the dictionary I retrieve from user defaults?

let defaults = UserDefaults.standard;
var myDict = [String: String]()
myDict["key"] = "value"

defaults.setValue(myDict, forKey: "myDict")


let mydict2 = defaults.object(forKey: "myDict") as? [String: String] ?? [String:String]()
print(mydict2)

2) What can I do to this code if the dictionary stores a custom class that I created as a value or a key so if the dictionary was like this:

class Car {
  var engineSize: Int
  var color: String

  init() {
    engineSize = 2000
    color = "blue"
  }

}

class Boat {    
  var surfaceArea: Int
  var weight: Int

  init() {    
    surfaceArea = 3500
    weight = 4000
  }
}

var myDict = [Car: Boat]()

how can I save that second dict to user defaults and read it from there?

Thank you

EDIT:

This is the answer suggested by ebby94:

var myDict = [String:String]()
myDict["key"] = "value";

let data = NSKeyedArchiver.archivedData(withRootObject: myDict)
UserDefaults.standard.set(data, forKey: "myDict")


func foo()

{
  guard let archivedData = UserDefaults.standard.value(forKey: "myDict") as? Data
    else
    {
        print("failed1")
        return
    }
  guard var unarchivedDictionary = NSKeyedUnarchiver.unarchiveObject(with: archivedData) as? [String:String]
    else
    {
        print("failed2")
        return
    }

    print(unarchivedDictionary["key"]!)
}

foo()

However this prints failed1, I'm assuming the data wasn't archived correctly. Can this be because I'm running it in playground?


回答1:


If you want to save custom object to userDefault first you need to encode & decode variable then save using archive & get data using unarchive.

class Car {
    var engineSize: Int
    var color: String

    init() {
        engineSize = 2000
        color = "blue"
    }
    // Decode
    required convenience public init(coder decoder: NSCoder)
    {
        self.init()

        if let engineSize = decoder.decodeObject(forKey: "engineSize") as? Int
        {
            self.engineSize = engineSize
        }
        if let color = decoder.decodeObject(forKey: "color") as? String
        {
            self.color = color
        }
    }

    // Encode
    func encodeWithCoder(coder : NSCoder)
    {
        if let engineSize = self.engineSize
        {
            coder.encode(engineSize, forKey: "engineSize")
        }
        if let color = self.color
        {
            coder.encode(color, forKey: "weight")
        }
    }
}

class Boat {
    var surfaceArea: Int
    var weight: Int

    init() {
        surfaceArea = 3500
        weight = 4000
    }

    // Decode
    required convenience public init(coder decoder: NSCoder)
    {
        self.init()

        if let surfaceArea = decoder.decodeObject(forKey: "surfaceArea") as? Int
        {
            self.surfaceArea = surfaceArea
        }
        if let weight = decoder.decodeObject(forKey: "weight") as? Int
        {
            self.weight = weight
        }
    }

    // Encode
    func encodeWithCoder(coder : NSCoder)
    {
        if let surfaceArea = self.surfaceArea
        {
            coder.encode(surfaceArea, forKey: "surfaceArea")
        }
        if let weight = self.weight
        {
            coder.encode(weight, forKey: "weight")
        }
    }



回答2:


You can't save a dictionary directly in UserDefaults. You'll have to convert the dictionary into data and save it and then retrieve the data and unarchive it into dictionary.

Archive and save to UserDefaults

    let myDict = [String:String]()
    let data = NSKeyedArchiver.archivedData(withRootObject: myDict)
    UserDefaults.standard.set(data, forKey: "myDict")

Retrieve and unarchive the data to dictionary

    guard let archivedData = UserDefaults.standard.value(forKey: "myDict") as? Data
        else{return}
    guard let unarchivedDictionary = NSKeyedUnarchiver.unarchiveObject(with: archivedData) as? [String:String]
        else{return}



回答3:


Userdefaults not work in Playground. you need to implement and start it in an App in Simulator



来源:https://stackoverflow.com/questions/41842494/user-defaults-not-saving-dictionary-contents-in-swift-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!