0

我创建了一个@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 {
    
}
4

1 回答 1

0

@Asperi 关于如何创建属性包装器是完全正确的。但是,这并不能解决TextField(). 问题似乎是你实际上并没有$quantity在你的 上使用TextField,而是使用来自格式化程序的字符串,$quantity.它似乎不允许更新机制正常工作。

但是,您可以简单地通过将@State字符串输入到 中来解决此问题TextField,然后更新.onChange(of:). 这允许您设置quantityIntTextField,并且最大值可以防止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
    }
}
于 2021-12-07T23:21:12.380 回答