使用 @AppStorage 进行设置的 SwiftUI 最佳实践:如何在加载 @AppStorage 之前读取 UserDefaults?
Posted
技术标签:
【中文标题】使用 @AppStorage 进行设置的 SwiftUI 最佳实践:如何在加载 @AppStorage 之前读取 UserDefaults?【英文标题】:SwiftUI best practice for using @AppStorage for settings: How to read the UserDefaults before the @AppStorage loaded? 【发布时间】:2021-02-22 00:09:04 【问题描述】:我使用@AppStorage 在设置视图中保存一些首选项,就像苹果推荐的那样:https://developer.apple.com/documentation/swiftui/settings
我还有一个主窗口,它会在用户打开设置视图之前读取一些首选项,然后似乎我会读取“错误的”UserDefaults,因为预期值未写入 UserDefaults,因为尚未加载设置视图。
例如:
// Settings view
struct SettingsView: View
@AppStorage("x") var x = 5 // give preference a default value
...
// Main view
struct MainView: View
func foo()
let x = UserDefaults.standard.double(forKey: "x")
// x is not the default value I expect
我知道的可能解决方案:
-
在应用启动时,检查 UserDefaults 是否为 nil,如果是,则使用默认值写入它们
读取 UserDefaults 时,检查 UserDefaults 是否为 nil,如果是,则改为读取默认值。
有没有更好的处理方法?谢谢!
【问题讨论】:
【参考方案1】:UserDefaults
提供了一个名为register
的方法,它使用“默认”(没有双关语)值加载它。这些值仅在实际存储在UserDefaults
中的那些键没有任何值的情况下使用。
我发现在应用启动时使用我的 AppDelegate 的应用包中的 plist 中的值填充它很有用(例如在didFinishLaunchingWithOptions
中——如果使用 SwiftUI 生命周期,您仍然可以这样做:SwiftUI app life cycle ios14 where to put AppDelegate code?) :
if let prefs = Bundle.main.path(forResource: "defaults", ofType: "plist"),
let dict = NSDictionary(contentsOfFile: prefs) as? [String : Any]
UserDefaults.standard.register(defaults: dict)
https://developer.apple.com/documentation/foundation/userdefaults/1417065-register
来自文档:
注册域的内容没有写入磁盘; 您需要在每次应用程序启动时调用此方法。您可以在应用程序的 Resources 目录中放置一个 plist 文件,然后使用从该文件中读取的内容调用 register(defaults:)。
使用这个系统,您不必费心检查自己的nil
值并决定是否加载默认值。而且,当您从 UserDefaults
读取支票时,您会在其中看到预填充的值。
【讨论】:
以上是关于使用 @AppStorage 进行设置的 SwiftUI 最佳实践:如何在加载 @AppStorage 之前读取 UserDefaults?的主要内容,如果未能解决你的问题,请参考以下文章
如何让@AppStorage 在 MVVM / SwiftUI 框架中工作?