将字典保存到UserDefaults中

10
我试图将一个字典存储在UserDefaults中,但每次代码运行时都会导致应用程序崩溃。以下是执行该代码时导致应用程序崩溃的示例代码。我尝试将其转换为NSDictionary或最初使其成为NSDictionary - 得到了相同的结果。

我尝试将一个字典存储在UserDefaults中,但每次代码运行时都会导致应用程序崩溃。以下是执行该代码时导致应用程序崩溃的示例代码。我尝试将其转换为NSDictionary或最初使其成为NSDictionary - 得到了相同的结果。

class CourseVC: UIViewController {

let test = [1:"me"]

override func viewDidLoad() {
    super.viewDidLoad()

    defaults.set(test, forKey: "dict1")

    }

}

也许是Int inkey的问题?尝试使用'let test = [1:"me"]'。可以工作吗? - user9215105
1
@Roman,你能分享一下你的崩溃日志吗?这对于调试你的应用程序非常有用。否则,我们无法确定出错的具体原因,因为一些源代码似乎丢失了(例如默认变量声明在哪里),而且你的源代码显示一个字典,但答案显示一个NSDictionary。如果你想使用后者,请考虑将第一个键设置为字符串。 - Mihir Thanekar
只有属性列表字典可以直接存储在用户默认设置中。属性列表字典必须具有字符串键。 - matt
2个回答

33

默认情况下,字典是可编码对象,您可以使用以下扩展将它们保存到UserDefaults中。

extension UserDefaults {
    func object<T: Codable>(_ type: T.Type, with key: String, usingDecoder decoder: JSONDecoder = JSONDecoder()) -> T? {
        guard let data = self.value(forKey: key) as? Data else { return nil }
        return try? decoder.decode(type.self, from: data)
    }

    func set<T: Codable>(object: T, forKey key: String, usingEncoder encoder: JSONEncoder = JSONEncoder()) {
        let data = try? encoder.encode(object)
        self.set(data, forKey: key)
    }
}

它们可以像这样使用:

let test = [1:"me"]
UserDefaults.standard.set(object: test, forKey: "test")

let testFromDefaults = UserDefaults.standard.object([Int: String].self, with: "test")

这个扩展和许多其他扩展都是SwifterSwift的一部分,你可能想在下一个iOS项目中使用它 :)


2
非常感谢您!这个扩展程序证明是最好的方式,它运行得非常出色! - Roman
2
顺便说一句,感谢你的SwifterSwift,我会好好学习并在我的其他项目中使用它。 - Roman
如果我有一个[String: Any]怎么办? - Pedro Paulo Amorim
@PedroPauloAmorim 任何对象都需要符合Codable协议,这样你的任何对象都可以进行编码。 - zeytin

1

如果要将带有非字符串键的NSDictionary存储在NSUserDefaults中,您需要首先将它们转换为NSData。尝试这个

let test = [1:"me"]
override func viewDidLoad() {
    super.viewDidLoad()
    let data = NSKeyedArchiver.archivedData(withRootObject: test)
    let defaults = UserDefaults.standard
    defaults.set(data, forKey: "dict1")
    if let data2 = defaults.object(forKey: "dict1") as? NSData {
        let dict = NSKeyedUnarchiver.unarchiveObject(with: data2 as Data)
        print(dict)
    }
}

1
我认为你不需要归档字典。请查看文档-> https://developer.apple.com/documentation/foundation/userdefaults - dahiya_boy
1
NSDictionary中非字符串键无法直接存储到Userdefaults中。 - Lenin
@Lenin 请仔细查看文档,其中明确提到UserDefault支持Dict。因此,请重新检查您在Xcode中的代码。 - dahiya_boy
2
在这份文档 https://developer.apple.com/documentation/foundation/nsdictionary 中明确提到,NSDictionaries的键必须是字符串。 - Lenin
@Lenin 谢谢你的回答。它有效。但是有一个问题。我在问题中提供的代码只是样例。我真正需要存储的字典是 [Int:Bool]。因此,在解档后,我发现所有的“true”和“false”都被替换为了1和0。换句话说,我的字典原本是 [1:true, 2:true, 3:false...],现在变成了 [1 = 1, 2 = 1, 3 = 0...]。所以,它不再是一个字典了。 - Roman
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接