【问题标题】:User Defaults not saving dictionary contents in swift 3用户默认值未在 swift 3 中保存字典内容
【发布时间】:2017-06-10 02:18:47
【问题描述】:

我正在尝试向字典添加键和值,然后将此字典添加为用户默认值并读回字典对象。我有两个问题非常感谢您的帮助,

1) 为什么从用户默认读取的字典是空的?由于我在字典中添加了一个键和一个值,不应该将它们保存到我从用户默认值检索的字典中吗?

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) 如果字典将我创建的自定义类存储为值或键,我可以对这段代码做什么,如果字典是这样的:

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]()

如何将第二个字典保存到用户默认值并从那里读取?

谢谢

编辑:

这是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()

但是打印失败 1,我假设数据未正确存档。这可能是因为我在操场上运行它吗?

【问题讨论】:

  • 首先确保你在一个真实的项目中测试它(playground 不起作用)
  • 第二个你需要让你的类 NSCoding 兼容。
  • 第三次使用 KeyedArchiever 将您的对象转换为数据
  • 也只需使用 set(yourObjectData, forKey: "theKey") 而不是 setValue
  • @LeoDabus 为什么要发布 6 个 cmets?发布答案或投票以作为骗子关闭(这必须是骗子)。

标签: ios swift dictionary nsuserdefaults


【解决方案1】:

如果您想先将自定义对象保存到 userDefault,您需要对变量进行编码和解码,然后使用存档保存并使用取消存档获取数据。

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")
        }
    }

【讨论】:

  • 非常感谢您的回复,您是否可以再解释一下代码。其中很多对我来说是新的,我想在使用它之前体面地理解它。需要什么便利? for self.surfaceArea = surfaceArea self 是解码器的对象吗?
【解决方案2】:

用户默认值在 Playground 中不起作用。您需要在模拟器中的应用程序中实现并启动它

【讨论】:

    【解决方案3】:

    您不能将字典直接保存在UserDefaults 中。您必须将字典转换为数据并保存,然后检索数据并将其解压缩到字典中。

    存档并保存到 UserDefaults

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

    检索数据并将其取消归档到字典

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

    【讨论】:

    • 我不确定在操场上如何处理 userdefaults。您可以尝试在新项目中执行此操作并更新结果吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 2017-03-09
    相关资源
    最近更新 更多