|
Please help me see if my solution is acceptable, or perhaps if there are better solutions or improvements please help me learn <3
(First time posting here, not sure about the format, hope I won't mess up.)
Cheers.
import SwiftUI
struct ContentView: View {
@State private var input = 0.0
@State private var output = 0.0
@State private var inputUnitIndex = "M"
@State private var outputUnitIndex = "M"
let mConvert = ["M": 1, "KM": 0.001, "FT": 3.280839, "YDS": 1.93613, "MI": 0.0006213]
let kmConvert = ["M": 1000, "KM": 1, "FT": 3280.839, "YDS": 1936.13, "MI": 0.6213]
let ftConvert = ["M": 0.3048, "KM": 0.0003048, "FT": 1, "YDS": 0.3333333, "MI": 0.0001893939]
let ydConvert = ["M": 0.9144, "KM": 0.0009144, "FT": 3, "YDS": 1, "MI": 0.0005681818]
let miConvert = ["M": 1609.344, "KM": 1.609344, "FT": 5280, "YDS": 1760, "MI": 1]
var outcome: Double {
var outcomeTotal: Double = 0.0
switch inputUnitIndex {
case "M":
outcomeTotal = (mConvert[outputUnitIndex] ?? 0) * input
case "KM":
outcomeTotal = (kmConvert[outputUnitIndex] ?? 0) * input
case "FT":
outcomeTotal = (ftConvert[outputUnitIndex] ?? 0) * input
case "YDS":
outcomeTotal = (ydConvert[outputUnitIndex] ?? 0) * input
case "MI":
outcomeTotal = (miConvert[outputUnitIndex] ?? 0) * input
default:
break
}
return outcomeTotal
}
let units = ["M", "KM", "FT", "YDS", "MI"]
var body: some View {
NavigationStack{
Form {
//input
Section {
Picker("UNIT", selection: $inputUnitIndex) {
ForEach(units, id: \.self) {
Text("\($0)")
}
}
.pickerStyle(.segmented)
.frame(height: 30)
TextField("input", value: $input, format:.number)
.keyboardType(.numberPad)
} header: {
Text("Input")
}
//output
Section{
Picker("UNIT", selection: $outputUnitIndex) {
ForEach(units, id: \.self) {
Text("\($0)")
}
}
.pickerStyle(.segmented)
.frame(height: 30)
Text(outcome, format:.number)
} header: {
Text("output")
}
}.navigationTitle("length conversion")
}
}
}
|
|
Think this one might for @Obelix who would probably give a better answer
Question to ask
- Does it work? - Yes this work and does what you want.
- Can it be Improved - Most code can.
- I must admit that this was a different way on doing the conversion then I had seen! Nice one
The only thing is that you are using a lot of string s, may think about using an enum instead.
Advantages
- Less likely to make typo mistakes
- Use
CaseIterable in the ForEach
switch is exhaustive, no need for default:
If you want to change then have a go. Will paste mine in the next post if you want to have a look.
|
|
struct ContentView: View {
enum Unit: String, CaseIterable {
case m, km, ft, yds, mi
var unitType: String {
self.rawValue.uppercased()
}
}
@State private var input = 0.0
@State private var output = 0.0
@State private var inputUnitIndex = Unit.m
@State private var outputUnitIndex = Unit.m
let mConvert: [Unit: Double] = [.m: 1, .km: 0.001, .ft: 3.280839, .yds: 1.93613, .mi: 0.0006213]
let kmConvert: [Unit: Double] = [.m: 1000, .km: 1, .ft: 3280.839, .yds: 1936.13, .mi: 0.6213]
let ftConvert: [Unit: Double] = [.m: 0.3048, .km: 0.0003048, .ft: 1, .yds: 0.3333333, .mi: 0.0001893939]
let ydConvert: [Unit: Double] = [.m: 0.9144, .km: 0.0009144, .ft: 3, .yds: 1, .mi: 0.0005681818]
let miConvert: [Unit: Double] = [.m: 1609.344, .km: 1.609344, .ft: 5280, .yds: 1760, .mi: 1]
var outcome: Double {
var outcomeTotal = 0.0
switch inputUnitIndex {
case .m:
outcomeTotal = (mConvert[outputUnitIndex] ?? 0) * input
case .km:
outcomeTotal = (kmConvert[outputUnitIndex] ?? 0) * input
case .ft:
outcomeTotal = (ftConvert[outputUnitIndex] ?? 0) * input
case .yds:
outcomeTotal = (ydConvert[outputUnitIndex] ?? 0) * input
case .mi:
outcomeTotal = (miConvert[outputUnitIndex] ?? 0) * input
}
return outcomeTotal
}
var body: some View {
NavigationStack{
Form {
//input
Section {
Picker("UNIT", selection: $inputUnitIndex) {
ForEach(Unit.allCases, id: \.self) {
Text("\($0.unitType)")
}
}
.pickerStyle(.segmented)
.frame(height: 30)
TextField("input", value: $input, format:.number)
.keyboardType(.numberPad)
} header: {
Text("Input")
}
//output
Section{
Picker("UNIT", selection: $outputUnitIndex) {
ForEach(Unit.allCases, id: \.self) {
Text("\($0.unitType)")
}
}
.pickerStyle(.segmented)
.frame(height: 30)
Text(outcome, format:.number)
} header: {
Text("Output")
}
}.navigationTitle("Length Conversion")
}
}
}
|
|
Based on the Dimension class and UnitLength subclass.
struct ContentView: View {
@State private var inputValue = 1.0
@State private var inputUnit = UnitLength.meters
@State private var outputUnit = UnitLength.meters
let unitTypes = [UnitLength.meters, UnitLength.kilometers, UnitLength.feet, UnitLength.yards, UnitLength.miles]
var body: some View {
NavigationStack{
Form {
Section {
TextField("From amount", value: $inputValue, format: .number)
.keyboardType(.decimalPad)
Picker("Convert from", selection: $inputUnit) {
ForEach(unitTypes, id: \.self) {
Text("\($0.symbol)")
}
}
.pickerStyle(SegmentedPickerStyle())
.padding(.horizontal)
} header: {
Text("Convert")
}
Section {
Text("\(Measurement(value: inputValue, unit: inputUnit).converted(to: outputUnit).value) \(outputUnit.symbol)")
Picker("Convert to", selection: $outputUnit) {
ForEach(unitTypes, id: \.self) {
Text("\($0.symbol)")
}
}
.pickerStyle(SegmentedPickerStyle())
.padding(.horizontal)
} header: {
Text("Converted to")
}
}.navigationTitle("Length Conversion")
}
}
}
|
|
Thank you both @NigelGee and @Greenamberred for the enlightment!
I'm really grateful for the new knowledge, might take a little time to sink in as both CaseIterable and Dimension are new to me.
@NigelGee as you mentioned, can't help curious how typical solution for this challenge looks like now :) anyhow, thanks for the kind word.
|