1

这是我现在用来将一个单位的值转换为另一个单位的函数。我正在寻找一个更动态的选择。我想让函数能够从例如:1 公斤转换为盎司,但是我现在这样做的原因我已经定义了每个单位与另一个单位的比较。有没有更简单的方法来做到这一点?

    func weightMath(_ input: UITextField, _ textField: UITextField) {
    //The math for doing weight calculations. This will also round up the answer to the third decimal.
    switch input.tag {
        /*
         case 0 is for when the user want to calculate from kilogram
         case 1 is for when the user want to calculate from ounces
         case 2 is for when the user want to calculate from pounds
         */
    case 0:
        switch textField.tag {
            /*
            case 0 is for when the user want to calculate to kilogram
            case 1 is for when the user want to calculate to ounces
            case 2 is for when the user want to calculate to pounds
            */
        case 0:
            textField.text = String(format: "%.3f", toFloat(input.text!) * 1)
        case 1:
            textField.text = String(format: "%.3f", toFloat(input.text!) * 35.274)
        case 2:
            textField.text = String(format: "%.3f", toFloat(input.text!) * 2.205)
        default:
            break
        }
    case 1:
        switch textField.tag {
            /*
            case 0 is for when the user want to calculate to kilogram
            case 1 is for when the user want to calculate to ounces
            case 2 is for when the user want to calculate to pounds
            */
        case 0:
            textField.text = String(format: "%.3f", toFloat(input.text!) * 0.028)
        case 1:
            textField.text = String(format: "%.3f", toFloat(input.text!) * 1)
        case 2:
            textField.text = String(format: "%.3f", toFloat(input.text!) * 0.063)
        default:
            break
        }
    case 2:
        switch textField.tag {
            /*
            case 0 is for when the user want to calculate to kilogram
            case 1 is for when the user want to calculate to ounces
            case 2 is for when the user want to calculate to pounds
            */
        case 0:
            textField.text = String(format: "%.3f", toFloat(input.text!) * 0.454)
        case 1:
            textField.text = String(format: "%.3f", toFloat(input.text!) * 16)
        case 2:
            textField.text = String(format: "%.3f", toFloat(input.text!) * 1)
        default:
            break
        }
    default:
        break
    }
}
4

1 回答 1

1

正如人们所提到的,使用MeasurementAPI 会简化事情,但我认为这不是您的代码的真正问题。您似乎意识到,随着您要转换的单位数量的增加,您的weightMath功能很快就会失控(如果您有 N 个单位,它将与 N^2 成正比增长)。很好的是,即使是初学者,您在查看此代码并认为“肯定有更好的方法”。

您缺少的关键见解是,您应该将其分为两个步骤,而不是直接从输入单元到输出单元。确定一些内部单位(比如千克),然后将输入转换为这些内部单位,然后从这些内部单位转换为输出单位。

让我们看一下在代码中的样子。尽管调用了您的函数,weightMath但它实际上确实会弄乱 UI 的东西。让我们通过将其分解为两个函数来解决这个问题:updateUI处理 UI 和convert进行数学运算。

这里的代码updateUI

func updateUI(_ input: UITextField, _ textField: UITextField) {
    guard let inputString = input.text,
          let inputValue = Double(inputString) else {
        // You may want to do more than just return.
        return
    }
    let convertedValue = convert(mass: inputValue, inputUnitIndex: input.tag, outputUnitIndex: textField.tag)
    textField.text = String(format: "%.3f", convertedValue)
}

现在convert可以专注于数学。即使不使用MeasurementAPI,我们也可以相当简单地实现:

private func convert(mass: Double, inputUnitIndex: Int, outputUnitIndex: Int) -> Double {
    let conversionTable = [ 1.0, 0.0283495, 0.453592 ]
    let massKg = mass * conversionTable[inputUnitIndex]
    return massKg / conversionTable[outputUnitIndex]
}

这里有几点说明。转换表包含通过乘法将公斤、盎司和磅转换为公斤所需的因子。这组相同的值可用于通过除法千克转换。该值massKg是我们内部单位的值,我选择为千克。

但是这段代码有点难看:它有魔法常数,如果你想支持更多的单位,你必须查找转换因子。使用MeasurementAPI 会使这更整洁。这就是它的样子。

private func convert(mass: Double, inputUnitIndex: Int, outputUnitIndex: Int) -> Double {
    let unitLookupTable = [ UnitMass.kilograms, UnitMass.ounces, UnitMass.pounds ]
    let massKg = Measurement(value: mass, unit: unitLookupTable[inputUnitIndex])
    return massKg.converted(to: unitLookupTable[outputUnitIndex]).value
}

仍然可以做更多的事情来让它变得更好:在这里传递整数并不是很好......但这是一个不同的故事。希望这会有所帮助。

于 2020-03-26T01:26:38.123 回答