【问题标题】:@propertywrapper in SwiftUISwiftUI 中的@propertywrapper
【发布时间】:2021-12-07 16:42:40
【问题描述】:

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

【问题讨论】:

标签: swift swiftui property-wrapper


【解决方案1】:

@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
    }
}

【讨论】:

    猜你喜欢
    • 2020-04-05
    • 1970-01-01
    • 1970-01-01
    • 2019-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多