properties - 无法使用 UseDefaults 的 propertyWrapper 调用类型“TextField<_>”的初始化程序
问题描述
我正在开发一个更新 UserDefaults 中的多个值的 SwiftUI 屏幕,以允许应用程序保留基本设置。我正在尝试使用 Combine 和 SwiftUI,因为这是一个原生 WatchOS 应用程序。
基本视图给了我一个错误,我认为这与 UserDefaults 的 propertyWrapper 有关,但由于我从未使用过 propertyWrapper(或就此而言的组合),我无法弄清楚如何解决这个问题。
这是属性包装器:
import Foundation
@propertyWrapper
struct UserDefault<T> {
let key: String
let defaultValue: T
init(_ key: String, defaultValue: T) {
self.key = key
self.defaultValue = defaultValue
}
var wrappedValue: T {
get {
UserDefaults(suiteName: "group.com.my.app")!.value(forKey: key) as? T ?? defaultValue
} set {
UserDefaults(suiteName: "group.com.my.app")!.set(newValue, forKey: key)
}
}
}
如您所见,它包装了 UserDefaults 的所有密钥对。
我的类同样非常简单,由两个 bool 和一个 double
import SwiftUI
import Foundation
import Combine
class Setup: ObservableObject {
private var notificationSubscription: AnyCancellable?
let objectWillChange = PassthroughSubject<Setup,Never>()
@UserDefault("keyOpt1Enabled", defaultValue: false)
var opt1Enabled: Bool {
willSet{
objectWillChange.send(self)
}
}
@UserDefault("keyOpt2Enabled", defaultValue: false)
var opt2Enabled: Bool {
willSet{
objectWillChange.send(self)
}
}
@UserDefault("keyValueDouble", defaultValue: Double(0.00))
var someValueDouble: Double {
willSet{
objectWillChange.send(self)
}
}
init() {
notificationSubscription = NotificationCenter.default.publisher(for: UserDefaults.didChangeNotification).sink { _ in
self.objectWillChange.send(self)
}
}
}
问题是在 SwiftUI 中我使用 TextField 来允许输入和更新双精度值
@ObservedObject var setup: Setup = Setup()
private var currencyFormatter: NumberFormatter = {
let f = NumberFormatter()
f.numberStyle = .currency
return f
}()
var body: some View {
ScrollView{
HStack{
TextField(self.$setup.someValueDouble,
formatter: currencyFormatter,
placeholder: "0.00",
onEditingChanged: {_ in
print("editing changed")
},
onCommit: {
print("updated")
}
)
}
HStack{
Button(action: {
self.setup.opt1Enabled = false
self.setup.opt2Enabled = true
} ) {
Text(verbatim: "Opt 1")
.font(Font.system(size: 16, design: Font.Design.rounded))
}
.background(setup.opt1Enabled ? Color.blue : Color.gray)
.disabled(self.setup.opt1Enabled)
.cornerRadius(5)
Button(action: {
self.setup.opt1Enabled = true
self.setup.opt2Enabled = false
}) {
Text(verbatim: "Opt 2")
}
.background(setup.opt2Enabled ? Color.blue : Color.gray)
.disabled(self.setup.opt2Enabled)
}
}
}
}
然后,TextField 给出无法推断通用参数“标签”的消息。Xcode 提供“修复”此问题,但最终结果是 TextField,这显然是不完整的,但整个程序中唯一的视图是“ContentView”,它是无效的。
解决方案
问题是TextField
' 的初始化程序首先将 aString
作为占位符,然后将其绑定到的值,因此它应该大致如下所示:
TextField("Placeholder",
value: self.$setup.someValueDouble,
formatter: currencyFormatter,
onEditingChanged: { _ in },
onCommit:{})
.keyboardType(.numberPad)
您可能想了解更多有关 TextFields 和 Formatter 的信息,因为它似乎是一个棘手的主题。