Лучший способ приблизиться к измерениям с разными типами юнитов - PullRequest
3 голосов
/ 11 марта 2020

Контекст:

Я пишу приложение, в котором я хочу отобразить данные о питании каждого пункта меню. Я хотел иметь гибкость преобразования, используя класс Measurement.

Проблема:

Проблема в том, что калории измеряются в Measurement , тогда как другие свойства, такие как белки, измеряются в Measurement < UnitMass>. Я решил создать переменную типа Measurement , чтобы она могла обрабатывать оба типа. Но тогда я теряю возможность делать преобразования или операции с переменной.

Эта функция выдаст мне ошибку (что имеет смысл, я просто не знаю, как лучше подходить к этому)

Двоичный оператор '/' не может быть применен к двум операндам 'Measurement *

func getPercentage() -> Double {
     return value / property.referenceIntake
}

Если я пытаюсь привести его, я получаю эту ошибку

Приведение из 'Measurement ' к несвязанному типу 'Measurement ' всегда терпит неудачу

if let massUnitMeasurement = value as? Measurement<UnitMass>, let referenceMeasurement = property.referenceIntake as? {
....
}

Что у меня есть до сих пор:

struct NutritionInformation {
    let property: NutritionProperties
    let value: Measurement<Unit>

    var formattedValue: String {
        let formatter = MeasurementFormatter()
        formatter.unitStyle = .medium
        formatter.unitOptions = .providedUnit
        return formatter.string(from: value)
    }
}

enum NutritionProperties {
    case calories
    case carbohydrate
    case cholesterol
    case fat
    case saturatedFat
    case fibre
    case protein
    case sodium
    case sugar

    var unit: Unit {
        switch self {
            case .calories: return UnitEnergy.kilocalories
            case .cholesterol, .sodium: return UnitMass.milligrams
            default: return UnitMass.grams
        }
    }

    var referenceIntake: Measurement<Unit> {
        switch self {
            case .calories: return Measurement(value: 2000, unit: unit)
            case .fat: return Measurement(value: 70, unit: unit)
            case .saturatedFat: return Measurement(value: 20, unit: unit)
            case .carbohydrate: return Measurement(value: 260, unit: unit)
            case .fibre: return Measurement(value: 30, unit: unit)
            case .sugar: return Measurement(value: 90, unit: unit)
            case .protein: return Measurement(value: 50, unit: unit)
            case .sodium: return Measurement(value: 2300, unit: unit)
            case .cholesterol: return Measurement(value: 300, unit: unit)
        }
    }
}

1 Ответ

0 голосов
/ 12 марта 2020

В конце я сделал приведение самого измерения к UnitMass или UnitEnergy (вместо приведения измерения <Измерение> к измерению ), а затем создал новое измерение с приведенным значением.

var percentage: Double {
        if let referenceAsMass = property.unit as? UnitMass, let valueAsMass = value.unit as? UnitMass {
            let valueMeasurement = Measurement(value: value.value, unit: valueAsMass)
            let referenceMeasurement = Measurement(value: property.referenceIntake.value, unit: referenceAsMass)
            return valueMeasurement.converted(to: .grams).value / referenceMeasurement.converted(to: .grams).value
        }
        if let referenceAsEnergy = property.unit as? UnitEnergy, let valueAsEnergy = value.unit as? UnitEnergy {
            let valueMeasurement = Measurement(value: value.value, unit: valueAsEnergy)
            let referenceMeasurement = Measurement(value: property.referenceIntake.value, unit: referenceAsEnergy)
            return valueMeasurement.converted(to: .calories).value / referenceMeasurement.converted(to: .calories).value
        }
        return value.value / property.referenceIntake.value
    }
...