表格货币输入

Form Currency Input

我正在寻求有关通过表单输入货币的帮助。我想要:

6 年前在 Limiting user input to a valid decimal number in Swift 上也有人问过类似的问题,但所有答案似乎都在使用 viewDidLoad。我认为这在表单条目中是不可行的。如果可行,请告诉我怎么做。谢谢

表格{
...

        // Enter entry amount
        Section {
            TextField("Enter Amount > " + curr, text: $moneyS)
                .keyboardType(.decimalPad)

        }
        
        // select entry save or cancel
        Section {
            Button(action: {
                self.showingAlert.toggle()
                
                ...

按照思路来实现,没有涵盖你的所有观点,但我认为自己进行就足够了:

class Test2Model: ObservableObject {
    @Published var currLimit: Double = 4.0
    @Published var digitLimit: Int = 2
    
    func getCurr(str: String) -> String{
        
        guard let currInserted = Double(str)
        else {
            return String(currLimit)
        }
        
        if currInserted <= currLimit {
            return String(currLimit)
        }
        return str
    }
}

struct Test2View: View {
    
    @ObservedObject private var test2Model = Test2Model()
    @State private var moneyS: String = ""
    
    var body: some View {
        
        Form {
        
            // Enter entry amount
            Section {
                TextField("Enter Amount > " + String(test2Model.currLimit), text: $moneyS)
                    .keyboardType(.decimalPad)
                    .onChange(of: moneyS, perform: { value in
                        guard let decimals = moneyS.components(separatedBy:".").last else {return}
                        if decimals.count > test2Model.digitLimit {
                            moneyS.removeLast()
                        }
                    })
            }
            
            // select entry save or cancel
            Section {
                Button(action: {
                    moneyS = test2Model.getCurr(str: moneyS)
                }, label: {
                    Text("Check")
                })
            }
        }
    }
}

struct Test2View_Previews: PreviewProvider {
    static var previews: some View {
        Test2View()
    }
}

你可以尝试这样的事情:

struct ContentView: View {
let maxDigits = 6
let maxDecimals = 2
let allowedCharacters = CharacterSet.decimalDigits.union(CharacterSet(charactersIn: NumberFormatter().decimalSeparator))

@State var money: Double?
@State var moneyText = ""

var body: some View {
    VStack (spacing: 30) {
        Spacer()
        TextField("enter a number", text: $moneyText)
            .padding(.horizontal, 20)
            .keyboardType(.decimalPad)
            .onChange(of: moneyText) {
                // to prevent pasting non-valid text
                let txt = [=10=].filter { ".0123456789".contains([=10=]) }
                if allowed(txt) {
                    money = Double(txt)
                    moneyText = txt
                } else {
                    moneyText = String(txt.dropLast())
                }
            }
        Text("Money value is: \(money ?? 0)")
        Spacer()
    }
}

func allowed(_ txt: String) -> Bool {
    let str = txt.trimmingCharacters(in: .whitespacesAndNewlines)
    switch str.components(separatedBy: ".").count - 1 {
    
    case 0:
        if str.count > maxDigits {
            return false
        }
        return allowedCharacters.isSuperset(of: CharacterSet(charactersIn: str))
        
    case 1:
        if str.starts(with: ".") && (str.count - 1) > maxDecimals {
            return false
        }
        let parts = str.split(separator: ".")
        if parts.count == 2 && (parts[1].count > maxDecimals) || (str.count - 1) > maxDigits {
            return false
        }
        return allowedCharacters.isSuperset(of: CharacterSet(charactersIn: str))
        
    default:
        return false
    }
}
}