我正在尝试找出构建一个绑定到UserDefaults的简单设置屏幕的最佳方法。
基本上,我有一个切换,我想:
- 此切换更改时要保存的UserDefault值(UserDefault应为真实值的来源)
- 切换到始终显示UserDefault的值
我已经观看了很多SwiftUI WWDC会议,但我仍然不确定我应该如何使用合并和SwiftUI中提供的不同工具来设置所有内容。我目前的想法是我应该使用BindableObject,这样我就可以使用hat来封装许多不同的设置。
我想我已经接近了,因为它几乎像预期的那样工作,但行为不一致。
当我在设备上构建和运行它时,我打开它并打开Toggle,然后如果我上下滚动视图一点,开关就会关闭(好像它实际上没有在UserDefaults中保存值)。
然而,如果我打开开关,离开应用程序,然后稍后回来它仍然开着,就像它记住了设置一样。
有什么建议吗?我希望这篇文章能帮助其他刚接触SwiftUI和合并的人,因为我在这个主题上找不到任何类似的问题。
import SwiftUI
import Combine
struct ContentView : View {
@ObjectBinding var settingsStore = SettingsStore()
var body: some View {
NavigationView {
Form {
Toggle(isOn: $settingsStore.settingActivated) {
Text("Setting Activated")
}
}
}.navigationBarTitle(Text("Settings"))
}
}
class SettingsStore: BindableObject {
var didChange = NotificationCenter.default.publisher(for: .settingsUpdated).receive(on: RunLoop.main)
var settingActivated: Bool {
get {
UserDefaults.settingActivated
}
set {
UserDefaults.settingActivated = newValue
}
}
}
extension UserDefaults {
private static var defaults: UserDefaults? {
return UserDefaults.standard
}
private struct Keys {
static let settingActivated = "SettingActivated"
}
static var settingActivated: Bool {
get {
return defaults?.value(forKey: Keys.settingActivated) as? Bool ?? false
}
set {
defaults?.setValue(newValue, forKey: Keys.settingActivated)
}
}
}
extension Notification.Name {
public static let settingsUpdated = Notification.Name("SettingsUpdated")
}
8条答案
按热度按时间iszxjhcz1#
更新
从iOS 14开始,现在有了一种非常非常简单的方法来读取和写入UserDefaults。
使用名为
@AppStorage
的新属性 Package 器以下是它的使用方法:
就是这样!它是如此简单和真正的直接向前。所有您的信息正在保存和读取的UserDefaults。
Swift 5.1中发生了很多变化。
BindableObject
已经完全弃用。此外,PassthroughSubject
也发生了重大变化。如果有人想让它工作,下面是同样的工作示例。我重用了"gohnjanotis"的代码,使它简单。
eeq64g8w2#
在this video by azamsharp和this tutorial by Paul Hudson的帮助下,我已经能够生成一个绑定到UserDefaults的切换,并显示您立即分配给它的任何更改。
在"window"变量下添加以下代码行
并修改window. rootViewController以显示此内容
如果您愿意,请创建一个名为以下内容的SwiftUI视图并粘贴:
不要忘记从您拥有的任何主视图将SettingsStore注入SettingsStoreMenu,例如
(Or你想用哪种方式都行。)
cs7cruho3#
此接缝工作良好:
扩展代码11.3.1
rbl8hiat4#
你也可以考虑用
EnvironmentObject
代替ObjectBinding
来代替this answer。使用对象绑定,切换将使用键
myBoolSetting
将用户默认值设置为true
/false
。您可以看到当前值反映在Text
视图的文本中。plupiseo5#
我发现的一个问题是,您使用了错误的API来设置/获取
UserDefaults
的值用途:6qqygrtg6#
这是我经过一些实验后得出的结果,使用
PassthroughSubject
而不是尝试对通知做一些事情,它似乎工作一致,正如预期的那样。我猜可能有一些Swift或SwiftUI技术可以简化这一过程,所以请指出其他一些方法。
guz6ccqo7#
您可以扩展
@Published
属性 Package 器以在UserDefaults
中存储值(如this answer中所建议的):下面是基于发布的问题的示例:
kq4fsx7k8#
以上选项对我都不起作用。在花了几个小时之后,我的工作诀窍是: