@propertywrapper in SwiftUI



我创建了一个@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设置为TextFieldInt值,最大值可防止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
}
}

最新更新