【问题标题】:Unit Conversion in SwiftUISwiftUI 中的单位转换
【发布时间】:2021-05-19 00:33:45
【问题描述】:

我目前正在开发一个单位转换应用程序,但遇到了一个问题,我仍在试图弄清楚如何解决它。该应用程序应该将一个单位转换为不同的单位,并且应该在每次将单位转换为不同的单位时转换并在文本视图中显示新值。(米到公里,英里到码等)。我创建了一个名为 result 的计算属性来处理转换,但是当我在模拟器中运行代码并在单位之间切换时,没有显示任何更改以显示成功转换的单位。我尝试在计算之前使用保护语句,因为在将 inputNumber 转换为整数后我认为 Value 为 0,但这似乎不起作用。我不确定我哪里出错了,但是对此的任何帮助将不胜感激。我在下面附上了代码和模拟器。 谢谢。

PS。我已经学会了如何并且可以使用 Apple 提供的测量功能来构建这个应用程序,我正在尝试通过基本上只使用数学计算来学习如何以不同的方式构建它。

struct ContentView: View {
    @State private var inputNumber = ""
    @State private var inputUnitValue = 2
    @State private var outputUnitValue = 2
    @State private var outputValue = ""
    
    let inputUnits = ["Feet", "Meters", "Kilometers", "Yard", "Miles"]
    let outputUnits = ["Feet", "Meters", "Kilometers", "Yard", "Miles"]
    
    var result: Double {
        
        var outputType = ""
        var inputType = ""
        
        let value = Double(inputNumber) ?? 0
        
        var output = Double(outputValue) ?? 0
        var input = Double(inputNumber) ?? 0
        
        
        guard value > 0 else {
            return 0
        }
        //Converts input value to input unit
        switch inputUnits[inputUnitValue] {
        case "meters":
            input = value * 3.28
        case "kilometers":
            input = value * 3280.84
        case "yards":
            input = value * 3
        case "miles":
            input = value * 5280
        case "feet":
            input = value * 1
        default:
            input = value * 3.28
        }
        
        //Converts input unit to output unit
        switch outputUnits[outputUnitValue] {
        case "meters":
            output = value / 3.28
        case "kilometers":
            output = value / 3280.84
        case "yards":
            output = value / 3
        case "miles":
            output = value / 5280
        case "feet":
            output = value / 1
        default:
            output = value / 3.28
        }
        
        return output
    }
    
    var body: some View {
        NavigationView {
            Form {
                Section {
                    TextField("Value", text: $inputNumber)
                        .keyboardType(.numberPad)
                    
                }
                Section(header: Text("Input Units")) {
                    Picker("Input Units", selection: $inputUnitValue) {
                        ForEach(0 ..< inputUnits.count) {
                            Text("\(self.inputUnits[$0])")
                        }
                    }
                    .pickerStyle(SegmentedPickerStyle())
                }
                Section(header: Text("Output Units")) {
                    Picker("Input Units", selection: $outputUnitValue) {
                        ForEach(0 ..< outputUnits.count) {
                            Text("\(self.outputUnits[$0])")
                        }
                    }
                    .pickerStyle(SegmentedPickerStyle())
                }
                Section (header: Text("output")){
                    Text("\(result, specifier: "%.2f")")
                }
            }
            .navigationBarTitle("Unit Conversion")
        }
    }
}

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

【问题讨论】:

标签: swift unit-testing swiftui


【解决方案1】:

switch 区分大小写。您的inputUnitsoutputUnits 大写...

let inputUnits = ["Feet", "Meters", "Kilometers", "Yard", "Miles"]

...而你的开关条件是小写的。

switch inputUnits[inputUnitValue] {
case "meters": /// lowercased
    ...
}

因此,您的switch 语句始终落入default

要修复,只需添加.lowercased()

switch inputUnits[inputUnitValue].lowercased() {
switch outputUnits[outputUnitValue].lowercased() {

还有一件事:我假设您的switches 的目的是:

  1. value 转换为标准英尺单位
  2. 将该英尺转换为输出单位

在这种情况下,在第二个 switch 中,您需要使用您的 input 变量(即转换为英尺的输入)执行计算 - 不是 value

为了让事情不那么混乱,我将input 重命名为inputAsFeet

var result: Double {
    
    let value = Double(inputNumber) ?? 0
    
    var inputAsFeet = Double(0)
    var output = Double(0)
    
    guard value > 0 else {
        return 0
    }
    
    switch inputUnits[inputUnitValue].lowercased() {
    case "meters":
        inputAsFeet = value * 3.28
    case "kilometers":
        inputAsFeet = value * 3280.84
    case "yards":
        inputAsFeet = value * 3
    case "miles":
        inputAsFeet = value * 5280
    case "feet":
        inputAsFeet = value * 1
    default:
        inputAsFeet = value * 3.28
    }

    switch outputUnits[outputUnitValue].lowercased() {
    case "meters":
        output = inputAsFeet / 3.28
    case "kilometers":
        output = inputAsFeet / 3280.84
    case "yards":
        output = inputAsFeet / 3
    case "miles":
        output = inputAsFeet / 5280
    case "feet":
        output = inputAsFeet / 1
    default:
        output = inputAsFeet / 3.28
    }
    
    return output
}

结果:

【讨论】:

  • 为什么不简单地使用相同的字符串而不是小写呢?顺便说一句,有一个专门用于此目的的测量类型,可以避免对值进行硬编码
  • @LeoDabus 是的,我同意。作为@JoakimDanielson said,枚举可能会更好。但无论如何,OP 说他们不想使用 Measurement - “仅使用数学计算”
  • @aheze,非常感谢您的帮助,我什至没有意识到我的输入单位大写了,该应用程序在修改后现在可以完美运行,如此小的变化但巨大的差异!谢谢。
  • @LeoDabus,我已经学会了使用测量类型,实际上我更喜欢使用它而不是硬编码,我只是想学习一种不同的方法来接近它。感谢您的帮助。
猜你喜欢
  • 2021-12-21
  • 2011-01-08
  • 1970-01-01
  • 1970-01-01
  • 2012-10-20
  • 2015-11-12
  • 1970-01-01
  • 2011-11-05
相关资源
最近更新 更多