I am making a unit converter app. It works well except for one issue. When I change the value of the second and third pickers and then change the value of the first picker, the app crashes. I suspect that this is because it is being set to an index out of range. Is there any way to fix this? Is it possible to set the values of fromUnitsIndex and toUnitsIndex back to 0 when the value of unitTypesIndex changes?
Here is the code:
func convert(_ value: Double, from sourceUnit: Dimension, to targetUnit: Dimension) -> Double {
let a = Measurement(value: value, unit: sourceUnit)
let b = a.converted(to: targetUnit).value
return b
}
struct ContentView: View {
@State private var fromUnitsIndex:Int = 0
@State private var toUnitsIndex:Int = 0
@State private var unitTypesIndex:Int = 0
private var unitTypesArr = ["Acceleration", "Angle", "Area", "Concentration of Mass", "Duration", "Electric Charge", "Electric Current", "Electric Potential Difference", "Electrical Resistance", "Energy", "Frequency", "Fuel Efficiency", "Length", "Mass", "Power", "Pressure", "Speed", "Temperature", "Volume"]
private var unitsArr = [["Meters Per Second Squared", "Gravity"], ["Degrees", "Radians", "Arc Minutes", "Arc Seconds", "Gradians", "Revolutions"], ["Square Nanometers", "Square Micrometers", "Square Millimeters", "Square Centimeters", "Square Meters", "Square Kilometers", "Square Megameters", "Square Inches", "Square Feet", "Square Yards", "Square Miles", "Acres", "Hectares", "Ares"], ["Grams Per Liter", "Milligrams Per Deciliter", "Millimoles Per Liter"], ["Seconds", "Minutes", "Hours"], ["Coulombs", "Microampere Hours", "Milliampere Hours", "Ampere Hours", "Kiloampere Hours", "Megaampere Hours"], ["Microamperes", "Milliamperes", "Amperes", "Kiloamperes", "Megaamperes"], ["Microvolts", "Millivolts", "Volts", "Kilovolts", "Megavolts"], ["Microohms", "Milliohms", "Ohms", "Kiloohms", "Megaohms"], ["Joules", "Kilojoules", "Calories", "Kilocalories", "Kilowatt Hours"], ["Nanohertz", "Microhertz", "Millihertz", "Hertz", "Kilohertz", "Megahertz", "Gigahertz", "Terahertz"], ["Liters Per 100 km", "Miles Per Gallon", "Miles Per Imperial Gallon"], ["Picometers", "Nanometers", "Micrometers", "Millimeters", "Centimeters", "Decimeters", "Meters", "Decameters", "Hectometers", "Kilometers", "Megameters", "Inches", "Feet", "Yards", "Miles", "Nautical Miles", "Light Years", "Astronomical Units", "Parsecs", "Fathoms", "Furlongs", "Scandinavian Miles"], ["Picograms", "Nanograms", "Micrograms", "Milligrams", "Centigrams", "Decigrams", "Grams", "Kilograms", "Metric Tons", "Ounces", "Pounds", "Stones", "Short Tons", "Carats", "Ounces Troy", "Slugs"], ["Femtowatts", "Picowatts", "Nanowatts", "Microwatts", "Milliwatts", "Watts", "Kilowatts", "Megawatts", "Gigawatts", "Terawatts", "Horsepower"], ["Pascals", "Hectopascals", "Kilopascals", "Megapascals", "Gigapascals", "Millibars", "Bars", "Pounds Per Square Inch", "Millimeters of Mercury", "Inches of Mercury"], ["Meters Per Second", "Kilometers Per Hour", "Miles Per Hour", "Knots"], ["Degrees Celsius", "Degrees Fahrenheit", "Degrees Kelvin"], ["Milliliters", "Centiliters", "Deciliters", "Liters", "Kiloliters", "Megaliters", "Cubic Millimeters", "Cubic Decimeters", "Cubic Meters", "Cubic Kilometers", "Fluid Ounces", "Cups", "Pints", "Quarts", "Gallons", "Cubic Inches", "Cubic Feet", "Cubic Yards", "Cubic Miles", "Acre Feet", "Bushels", "Teaspoons", "Tablespoons", "Imperial Teaspoons", "Imperial Tablespoons", "Imperial Fluid Ounces", "Imperial Pints", "Imperial Quarts", "Imperial Gallons", "Metric Cups"]]
private var convUnitsArr = [[UnitAcceleration.metersPerSecondSquared, UnitAcceleration.gravity], [UnitAngle.degrees, UnitAngle.radians, UnitAngle.arcMinutes, UnitAngle.arcSeconds, UnitAngle.gradians, UnitAngle.revolutions], [UnitArea.squareNanometers, UnitArea.squareMicrometers, UnitArea.squareMillimeters, UnitArea.squareCentimeters, UnitArea.squareMeters, UnitArea.squareKilometers, UnitArea.squareMegameters, UnitArea.squareInches, UnitArea.squareFeet, UnitArea.squareYards, UnitArea.squareMiles, UnitArea.acres, UnitArea.hectares, UnitArea.ares], [UnitConcentrationMass.gramsPerLiter, UnitConcentrationMass.milligramsPerDeciliter, UnitConcentrationMass.millimolesPerLiter], [UnitDuration.seconds, UnitDuration.minutes, UnitDuration.hours], [UnitElectricCharge.coulombs, UnitElectricCharge.microampereHours, UnitElectricCharge.milliampereHours, UnitElectricCharge.ampereHours, UnitElectricCharge.kiloampereHours, UnitElectricCharge.megaampereHours], [UnitElectricCurrent.microamperes, UnitElectricCurrent.milliamperes, UnitElectricCurrent.amperes, UnitElectricCurrent.kiloamperes, UnitElectricCurrent.megaamperes], [UnitElectricPotentialDifference.microvolts, UnitElectricPotentialDifference.millivolts, UnitElectricPotentialDifference.volts, UnitElectricPotentialDifference.kilovolts, UnitElectricPotentialDifference.megavolts], [UnitElectricResistance.microohms, UnitElectricResistance.milliohms, UnitElectricResistance.ohms, UnitElectricResistance.kiloohms, UnitElectricResistance.megaohms], [UnitEnergy.joules, UnitEnergy.kilojoules, UnitEnergy.calories, UnitEnergy.kilocalories, UnitEnergy.kilowattHours], [UnitFrequency.nanohertz, UnitFrequency.microhertz, UnitFrequency.millihertz, UnitFrequency.hertz, UnitFrequency.kilohertz, UnitFrequency.megahertz, UnitFrequency.gigahertz, UnitFrequency.terahertz], [UnitFuelEfficiency.litersPer100Kilometers, UnitFuelEfficiency.milesPerGallon, UnitFuelEfficiency.milesPerImperialGallon], [UnitLength.picometers, UnitLength.nanometers, UnitLength.micrometers, UnitLength.millimeters, UnitLength.centimeters, UnitLength.decimeters, UnitLength.meters, UnitLength.decameters, UnitLength.hectometers, UnitLength.kilometers, UnitLength.megameters, UnitLength.inches, UnitLength.feet, UnitLength.yards, UnitLength.miles, UnitLength.nauticalMiles, UnitLength.lightyears, UnitLength.astronomicalUnits, UnitLength.fathoms, UnitLength.furlongs, UnitLength.scandinavianMiles], [UnitMass.picograms, UnitMass.nanograms, UnitMass.micrograms, UnitMass.milligrams, UnitMass.centigrams, UnitMass.decigrams, UnitMass.grams, UnitMass.kilograms, UnitMass.metricTons, UnitMass.ounces, UnitMass.pounds, UnitMass.stones, UnitMass.shortTons, UnitMass.carats, UnitMass.ouncesTroy, UnitMass.slugs], [UnitPower.femtowatts, UnitPower.picowatts, UnitPower.nanowatts, UnitPower.microwatts, UnitPower.milliwatts, UnitPower.watts, UnitPower.kilowatts, UnitPower.megawatts, UnitPower.gigawatts, UnitPower.terawatts, UnitPower.horsepower], [UnitPressure.newtonsPerMetersSquared, UnitPressure.hectopascals, UnitPressure.kilopascals, UnitPressure.megapascals, UnitPressure.gigapascals, UnitPressure.millibars, UnitPressure.bars, UnitPressure.poundsForcePerSquareInch, UnitPressure.millimetersOfMercury, UnitPressure.inchesOfMercury], [UnitSpeed.metersPerSecond, UnitSpeed.kilometersPerHour, UnitSpeed.milesPerHour, UnitSpeed.knots], [UnitTemperature.celsius, UnitTemperature.fahrenheit, UnitTemperature.kelvin], [UnitVolume.milliliters, UnitVolume.centiliters, UnitVolume.deciliters, UnitVolume.liters, UnitVolume.kiloliters, UnitVolume.megaliters, UnitVolume.cubicMillimeters, UnitVolume.cubicDecimeters, UnitVolume.cubicMeters, UnitVolume.cubicKilometers, UnitVolume.fluidOunces, UnitVolume.cups, UnitVolume.pints, UnitVolume.quarts, UnitVolume.gallons, UnitVolume.cubicInches, UnitVolume.cubicFeet, UnitVolume.cubicYards, UnitVolume.cubicMiles, UnitVolume.acreFeet, UnitVolume.bushels, UnitVolume.teaspoons, UnitVolume.tablespoons, UnitVolume.imperialTeaspoons, UnitVolume.imperialTablespoons, UnitVolume.imperialFluidOunces, UnitVolume.imperialPints, UnitVolume.imperialQuarts, UnitVolume.imperialGallons, UnitVolume.metricCups]]
@State private var inputValue:String = ""
var body: some View {
GeometryReader { geometry in
VStack {
Text("Unit Converter").font(.largeTitle).fontWeight(.semibold)
Spacer()
HStack(spacing: 0){
VStack {
Spacer()
TextField("Enter a value", text: self.$inputValue)
.textFieldStyle(RoundedBorderTextFieldStyle())
.keyboardType(.decimalPad)
.frame(width: geometry.size.width/2.5)
Text("\(self.unitsArr[self.unitTypesIndex][self.fromUnitsIndex])")
.lineLimit(1)
.minimumScaleFactor(0.5)
.foregroundColor(.white)
}
.frame(minWidth: 0, maxWidth: .infinity)
Spacer()
Text("=")
.font(.title)
.foregroundColor(.white)
Spacer()
VStack (spacing: 10){
Spacer()
Text("\(convert((self.inputValue as NSString).doubleValue, from: UnitAcceleration.metersPerSecondSquared, to: UnitAcceleration.metersPerSecondSquared))")
.frame(width: geometry.size.width/2.5)
.foregroundColor(.white)
Text("\(self.unitsArr[self.unitTypesIndex][self.toUnitsIndex])")
.lineLimit(1)
.minimumScaleFactor(0.5)
.foregroundColor(.white)
}
.frame(minWidth: 0, maxWidth: .infinity)
}
.frame(maxWidth: geometry.size.width/1.15, maxHeight: geometry.size.height/9)
.padding()
.background(Color.blue)
.cornerRadius(25.0)
Spacer()
VStack {
Text("Unit Type")
.fontWeight(.medium)
.foregroundColor(.white)
.font(.title)
Picker(selection: self.$unitTypesIndex, label: Text("Unit Type").foregroundColor(.white)) {
ForEach(0..<self.unitTypesArr.count) { index in
Text(self.unitTypesArr[index])
.foregroundColor(.white)
.fontWeight(.semibold)
.tag(index)
}
}
.frame(maxHeight: geometry.size.height/9)
.clipped()
.labelsHidden()
.pickerStyle(DefaultPickerStyle())
}
.padding()
.background(Color.blue)
.cornerRadius(25.0)
VStack {
Text("Convert From")
.fontWeight(.medium)
.foregroundColor(.white)
.font(.title)
Picker(selection: self.$fromUnitsIndex, label: Text("Unit Type").foregroundColor(.white)) {
ForEach(0..<self.unitsArr[self.unitTypesIndex].count) { index in
Text(self.unitsArr[self.unitTypesIndex][index])
.foregroundColor(.white)
.fontWeight(.semibold)
.tag(index)
}
}
.id(self.unitTypesIndex*10+self.fromUnitsIndex)
.frame(maxHeight: geometry.size.height/9)
.clipped()
.labelsHidden()
.pickerStyle(DefaultPickerStyle())
}
.padding()
.background(Color.blue)
.cornerRadius(25.0)
VStack {
Text("Convert To")
.fontWeight(.medium)
.foregroundColor(.white)
.font(.title)
Picker(selection: self.$toUnitsIndex, label: Text("Unit Type").foregroundColor(.white)) {
ForEach(0..<self.unitsArr[self.unitTypesIndex].count) { index in
Text(self.unitsArr[self.unitTypesIndex][index])
.foregroundColor(.white)
.fontWeight(.semibold)
.tag(index)
}
}
.id(self.unitTypesIndex*10+self.toUnitsIndex)
.frame(maxHeight: geometry.size.height/9)
.clipped()
.labelsHidden()
.pickerStyle(DefaultPickerStyle())
}
.padding()
.background(Color.blue)
.cornerRadius(25.0)
Spacer()
}
.padding()
}
}
}