简体   繁体   English

在 SwiftUI 中将选取器更改为文本字段

[英]Changing A Picker to a TextField in SwiftUI

I'm a newbie self teaching myself iOS development (100DaysOfSwiftUI by Paul Hudson, Project 1), and currently I came across a problem that I haven't been able to solve yet.我是一个自学 iOS 开发的新手(Paul Hudson 的 100DaysOfSwiftUI,项目 1),目前我遇到了一个我还没有解决的问题。 Originally, the numberOfPeople section had a picker with below code, which I'm trying to change to a text field.最初,numberOfPeople 部分有一个带有以下代码的选择器,我试图将其更改为文本字段。 Started by changing its @State property (@State private var numberOfPeople = 2) from 2 to empty string, and tried creating another computed property for people count.首先将其 @State 属性 (@State private var numberOfPeople = 2) 从 2 更改为空字符串,并尝试为人数创建另一个计算属性。 when the number of people text field is left empty, 0 doesn't appear as default on the simulator on the amount per person section when I run the project, instead NaN appears as in the screenshot below.当人数文本字段留空时,当我运行项目时,模拟器上每人数量部分的默认值不会显示为 0,而是显示为 NaN,如下面的屏幕截图所示。 (Which makes me wonder if numberOfPeople converted successfully to an Integer through nil coalescing as below). (这让我想知道 numberOfPeople 是否通过如下 nil 合并成功转换为 Integer)。 Only time the project functions as it should is when I enter a value in the number of people text field.只有当我在人数文本字段中输入值时,项目才能正常运行。 I'm not 100% sure where I went wrong with this, but any help will be greatly appreciated!!我不是 100% 确定我哪里出错了,但是任何帮助都将不胜感激!

struct ContentView: View {
    @State private var checkAmount = ""
    @State private var numberOfPeople = ""
    @State private var tipPercentage = 2
    
    let tipPercentages = [10,15,20,25,0]
    let allPeople = 2...100

    var totalPerPerson: Double {
        let peopleCount = Double(numberOfPeople) ?? 0
        let tipSelection = Double(tipPercentages[tipPercentage])
        let orderAmount = Double(checkAmount) ?? 0
        
        let tipValue = orderAmount / 100 * tipSelection
        let grandTotal = orderAmount + tipValue
        let amountPerPerson = grandTotal / peopleCount

        return amountPerPerson
    }
    
    var grandTotal: Double {
        let tipSelection = Double(tipPercentages[tipPercentage])
        let orderAmount = Double(checkAmount) ?? 0
        
        let tipValue = orderAmount / 100 * tipSelection
        let totalAmount = orderAmount + tipValue
        
        return totalAmount
    }
    
    var body: some View {
        NavigationView {
            Form {
                Section {
                    TextField("Amount", text: $checkAmount)
                        .keyboardType(.decimalPad)
                    
                    TextField("Number of people", text: $numberOfPeople)
                        .keyboardType(.numberPad)
                }
                
                Section(header: Text("How much tip do you want to leave?")) {
                    Picker("Tip percentage", selection: $tipPercentage) {
                        ForEach(0 ..< tipPercentages.count) {
                            Text("\(self.tipPercentages[$0])%")
                        }
                    }
                    .pickerStyle(SegmentedPickerStyle())
                }
                
                Section (header: Text("Total Amount")){
                    Text("$\(grandTotal, specifier: "%.2f")")
                }
                
                Section (header: Text("Amount Per Person")){
                    Text("$\(totalPerPerson, specifier: "%.2f")")
                }
            }
            .navigationBarTitle("WeSplit")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

(Original code for picker)
Picker("Number of people", selection: $numberOfPeople) {
        ForEach(2 ..< 100) {
            Text("\($0) people")

(Original code for people count)
let peopleCount = Double(numberOfPeople + 2)

project simulator项目模拟器

What you're seeing is a result of trying to divide by zero.你看到的是试图除以零的结果。 You can avoid that calculation by returning 0 from your totalPerPerson function if peopleCount is 0 before doing the division using something like this:如果在使用以下方法进行除法之前, peopleCount0 ,则可以通过从totalPerPerson function 返回0来避免该计算:

var totalPerPerson: Double {
    let peopleCount = Double(numberOfPeople) ?? 0
    let tipSelection = Double(tipPercentages[tipPercentage])
    let orderAmount = Double(checkAmount) ?? 0
    
    guard peopleCount > 0 else {
        return 0
    }
    
    let tipValue = orderAmount / 100 * tipSelection
    let grandTotal = orderAmount + tipValue
    let amountPerPerson = grandTotal / peopleCount

    return amountPerPerson
}

Keep in mind that with your new TextField , as opposed to the picker, even if you specify .decimalPad or .numberPad , there are still ways for the user to enter non-numerical values in those fields, so you'd probably want to put up an error if that happens (or, search here on SO for solutions about fields that only accept numbers).请记住,使用新的TextField ,而不是选择器,即使您指定.decimalPad.numberPad ,用户仍然可以在这些字段中输入非数字值,因此您可能想要输入如果发生这种情况,则会出现错误(或者,在 SO 上搜索有关仅接受数字的字段的解决方案)。 An example for such a TextField is specified in this solution解决方案中指定了此类 TextField 的示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM