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

Posted

技术标签:

【中文标题】将变量与 UserDefaults 同步的正确方法【英文标题】:Right way to sync a variable with UserDefaults 【发布时间】:2017-10-18 07:57:48 【问题描述】:

我想在设置值时直接与 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 中?

更新

这是我在操场上的东西:

【问题讨论】:

您是否尝试过调试并检查newValue 的外观? 【参考方案1】:

简短回答:是的。

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

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

您可以像这样在操场上轻松验证此行为:

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


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

【讨论】:

【参考方案2】:

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

是的。

乍一看,你有一个 setter,作为一个 setter,它只在你进行新赋值时才观察值,例如:

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

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

【讨论】:

以上是关于将变量与 UserDefaults 同步的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

多线程之:正确使用 Volatile 变量

使用 UserDefaults 保存数据的正确事件是啥?

将 Laravel 模型与外部 API 数据源同步的正确方法是啥?

保存到 UserDefaults 被调用 19 次

Java 理论与实践: 正确使用 Volatile 变量

正确使用 Volatile 变量