将变量与 UserDefaults 同步的正确方法

Right way to sync a variable with UserDefaults

我想在设置值时直接与 UserDefaults 保持变量同步。我是这样做的:

var userId: String {
    get {
        return UserDefaults.standard.string(forKey: kUserIdKey) ?? ""
    }
    set {
        UserDefaults.standard.set(newValue, forKey: kUserIdKey)
    }
}

它运行良好,但这样做是否正确?

如果是这样,数组呢?

var tagsList: [Int] {
    get {
        return (UserDefaults.standard.object(forKey: kTagsList) as? [Int]) ?? [Int]()
    }
    set {
        UserDefaults.standard.set(newValue, forKey: kTagsList)
    }
}

如果我添加一个元素 tagsList.append(0),新值是否存储在 UserDefaults 中?

更新

这是我在操场上的东西:

简答:是。

长答案:数组和字符串是 Swift 中的 struct,它们在变异时语义上会生成一个全新的副本。

因此,setter 中的 newValue 是您对数组应用的任何变异的结果数组,无论它是 append 还是其他变异函数。

您可以像这样在 playground 中轻松验证此行为:

var array: [Int] {
    get { return [1, 2, 3] }
    set { print(newValue) }
}

array.append(4)
// Prints [1, 2, 3, 4]

If I add an element tagsList.append(0), is the new value stored in UserDefaults?

是。

乍一看,你有一个 setter 并且,作为一个 setter,它只会在你进行新分配时观察值,例如:

tagsList = [1,2,3] // 新值。

如果 Array<Int> ([Int]) 是 class 我们可以说,即使您确实通过调用 append 修改了现有数组,这也不是赋值, 本身。但是,[Int] 不是 class,它是 struct,这意味着任何修改( 突变 的函数都是正确的)现有 struct,基本上会导致一个新的任务。这就是为什么您会看到 setter 触发的原因。