我创建了一个@propertyWrapper来限制变量可以达到的数量。我在SwiftUI视图中尝试了它,其中有一个按钮可以增加变量的值,它有效,变量停止在初始值设定项中设置的最大值。然而,如果我用Textflied尝试它,它不起作用,如果我插入一个比一集更高的数字,什么都没有发生,它让我去做。我该如何解决这个问题,我知道这个问题与绑定有关,但我不知道它到底是什么,这是代码:
import SwiftUI
struct ContentView: View {
@Maximum(maximum: 12) var quantity: Int
var body: some View {
NavigationView{
Form{
TextField("", value: $quantity, format: .number, prompt: Text("Pizza").foregroundColor(.red))
Button {
quantity += 1
} label: {
Text("(quantity)")
}
}
}
}
}
@propertyWrapper
struct Maximum<T: Comparable> where T: Numeric {
@State private var number: T = 0
var max: T
var wrappedValue: T {
get { number }
nonmutating set { number = min(newValue, max) }
}
var projectedValue: Binding<T> {
Binding(
get: { wrappedValue },
set: { wrappedValue = $0 }
)
}
init(maximum: T){
max = maximum
}
}
extension Maximum: DynamicProperty {
}
@Asperi非常正确。然而,这并不能解决TextField()
的问题。问题似乎是,您实际上并没有在TextField
上使用$quantity
,而是使用了从$quantity.
派生的格式化程序中的字符串。这似乎不允许更新机制正常工作。
但是,只需将@State
字符串输入到TextField
中,然后更新.onChange(of:)
中的所有内容,就可以解决此问题。这允许您将quantity
设置为TextField
的Int
值,最大值可防止quantity
过高。然后转身将字符串设置为quantity.description
以保持所有内容的同步。
最后一件事,我把keyboardType
改成了.decimalPad
,使输入更容易。
struct ContentView: View {
@Maximum(maximum: 12) var quantity: Int
@State private var qtyString = "0"
var body: some View {
NavigationView{
Form{
TextField("", text: $qtyString, prompt: Text("Pizza").foregroundColor(.red))
.onChange(of: qtyString) { newValue in
if let newInt = Int(newValue) {
quantity = newInt
qtyString = quantity.description
}
}
.keyboardType(.decimalPad)
Button {
quantity += 1
} label: {
Text("(quantity)")
}
}
}
}
}
@propertyWrapper
struct Maximum<T: Comparable>: DynamicProperty where T: Numeric {
let number: State<T> = State(initialValue: 0)
var max: T
var wrappedValue: T {
get { number.wrappedValue }
nonmutating set { number.wrappedValue = min(newValue, max) }
}
var projectedValue: Binding<T> {
Binding(
get: { wrappedValue },
set: { wrappedValue = $0 }
)
}
init(maximum: T){
max = maximum
}
}