首页 > 解决方案 > 如何在 Swift 中正确存储用户设置?

问题描述

我想知道在 Swift 中存储用户设置的最佳方式是什么。对于用户设置,我的意思是简单(小)数据,而不是一些大文件。到目前为止,我使用了一个包含我想要保存的所有属性的类。

所有这些属性都符合 Codable。但是,我没有将整个类保存在 UserDefaults 中,而是单独保存了每个属性。但我不喜欢这种方法。它有几个问题:代码变得更长,因为我必须为每个变量编写 didSet{...}。例如:

var percentage: Double = UserDefaults.standard.double(forKey: "percentage")  {
        didSet {
            UserDefaults.standard.set(percentage, forKey: "percentage")
        }
    }

可以看到,这里变量名写了4次。所以很有可能出现拼写错误/复制和粘贴错误。

那我为什么不保存整个班级呢?好吧,我注意到如果我在类中添加一个变量,类的解码将不再起作用,并且即使我给新变量一个默认值,所有数据也会丢失。

似乎有一种方法可以解决这个问题:手动解码。例如:

 required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        id = try container.decode(UUID.self, forKey: .id)
        name = try container.decode(String.self, forKey: .name)
        //etc...
    }

但是,手动解码似乎需要我分别解码每个变量。我也不喜欢这样,因为也很有可能忘记一个变量等(所以它与上面的问题相同)。

我还想做的是让用户选择导出和导入设置以及使用 iCloud 进行设置同步。对于前者,最好存储整个 Settings 类(我可以导出和导入 JSON 文件)。

有没有聪明的方法来做到这一点?

谢谢你的协助!

标签: iosswiftpersistence

解决方案


您可能还需要某种类来管理所有用户的东西,如下所示:

class SettingsManager {
    
    private let defaults = UserDefaults.standard
    
    var percentage: Double {
        get { return defaults.value(forKey: "percentage") as? Double ?? 0.0 }
        set { defaults.set(newValue, forKey: "percentage") }
    }
    
}

这样,您可以将所需的代码量减少到:

// Retrieve a value
let percentage = SettingsManager().percentage
// Set new value
SettingsManager().percentage = 0.55

理想情况下,您可以使用此处描述的属性包装器。这消除了对值进行编码/解码的需要,直到它成为自定义类型。


推荐阅读