【问题标题】:UserDefaults is not saved with SwiftUserDefaults 不使用 Swift 保存
【发布时间】:2017-05-09 04:38:04
【问题描述】:

我正在尝试使用 UserDefaults 持久保存布尔值。这是我的代码:

public static var isOffline = UserDefaults.standard.bool(forKey: "isOffline") {
    didSet {
        print("Saving isOffline flag which is now \(isOffline)")
        UserDefaults.standard.set(isOffline, forKey: "isOffline")
        UserDefaults.standard.synchronize()
    }
}

为什么不工作?这段代码有什么问题?

问题是当我尝试从UserDefaults 检索"isOffline" 密钥时,我总是得到一个false

我在行的 .onChange 方法中设置了 isOffline(我使用 Eureka 作为框架来创建表单)。该标志在应用程序的生命周期内保持正确的值,但是当我关闭它时,该值可能会以某种方式被删除。

【问题讨论】:

  • 您的代码在什么方面不起作用?请告诉我们minimal reproducible example
  • 另请注意,您无需在每次更改用户默认值时都调用synchronize()——仅当您特别需要系统保存用户时立即默认(例如,当您的应用程序即将终止时) - 请参阅this Q&A
  • 是的,你是对的。但是现在的问题是“isOffline”标志总是返回false
  • 你在哪里设置isOffline
  • @Hamish 我添加了更多细节

标签: ios swift save nsuserdefaults


【解决方案1】:

我遇到了同样的问题,问题出在“didSet”块本身。我不知道为什么,但它不适用于 userDefaults - 它不能正确持久化,并且在终止应用程序后所有更改都消失了。

Synchronize() 没有帮助。我发现,这个方法不再需要,将来会被弃用(这是 UserDefaults 类中的注释):

-synchronize 已弃用,将在未来版本中使用 NS_DEPRECATED 宏进行标记。

通过反复试验,我发现如果我从主线程调用它,它可以工作:

public static var isOffline = UserDefaults.standard.bool(forKey: "isOffline") {
    didSet {
        print("Saving isOffline flag which is now \(isOffline)")
        DispatchQueue.main.async {
            UserDefaults.standard.set(isOffline, forKey: "isOffline")
        }
    }
}

如果有人能解释一下,为什么它在主线程上起作用,而在其他线程上不起作用,我会很高兴听到它。

【讨论】:

  • "在运行时,您使用 UserDefaults 对象从用户的默认数据库中读取您的应用程序使用的默认值。UserDefaults 缓存信息以避免每次您需要默认值时都必须打开用户的默认数据库. 当您设置默认值时,它会在您的进程内同步更改,并异步更改为持久存储和其他进程。”这可能是因为缓存和在主线程上进行更改可能是即时写入默认值的原因。
【解决方案2】:

尝试改变

UserDefaults.standard.set(isOffline, forKey: "isOffline")

UserDefaults.standard.setValue(isOffline, forKey: "isOffline")

没有调度代码

【讨论】:

  • 你知道为什么 set() 函数不起作用吗?因为它在我的设备上似乎有点随机。有时它有效,有时它适用于几个值。有时它不会。奇怪的是。有时我存储这些值,然后加载它们却一无所获。然后我重新启动应用程序,突然一些值又回来了。使用 setValue,这些问题看起来就消失了。但我真的很想知道为什么! :)
  • 对不起,我不知道原因,因为我很高兴它为我们所有人工作。苹果以神秘的方式运作:p
【解决方案3】:

这样做,

public static var isOffline:Bool {
    get {
       return UserDefaults.standard.bool(forKey: "isOffline")
    }
    set(newValue) {
        print("Saving isOffline flag which is now \(isOffline)")
        UserDefaults.standard.set(newValue, forKey: "isOffline")
        UserDefaults.standard.synchronize()
    }
}

【讨论】:

  • 您的第一个示例不起作用,因为您要绑定的所谓的“newValue”实际上是属性的旧值。但是这两个例子都没有回答 OP 的“这段代码有什么问题?”的问题。
  • 第一个例子也有效。我亲自测试过,然后才发布。
  • 我这几天一直在苦苦调试...而它所需要的只是 .synchronize
  • 但是,如果您查看函数描述 developer.apple.com/documentation/foundation/nsuserdefaults/… :“等待任何对默认数据库的未决异步更新并返回;此方法是不必要的,不应使用。”
猜你喜欢
  • 1970-01-01
  • 2018-07-23
  • 1970-01-01
  • 1970-01-01
  • 2019-01-12
  • 2014-12-15
  • 1970-01-01
  • 1970-01-01
  • 2015-03-07
相关资源
最近更新 更多