簡體   English   中英

SwiftUI 中的@propertywrapper

[英]@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
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM