|
Hi All. I completed the challenge and the code seems to work but would like to see if there is a better coding solution.
I would also like to learn how to format the "Imperial Number" text view to limit it to decimals. I tried using specifier: "%.2f", but it returns an error, and I think its an issue with converting Measurement(UnitLength), which is beyond my understanding at this point. Thanks for any advice.
import SwiftUI
struct ContentView: View {
@State private var inputNumber = ""
@State private var inputUnit = 0
@State private var outputUnit = 0
let inputUnits = ["Millimeters", "Centimeters", "Meters", "Kilometers"]
let outputUnits = ["Inches", "Feet", "Yards", "Miles"]
// Convert the user’s input to a single base unit (millimeters).
var metricConversion: Double {
let metric = Double(inputNumber) ?? 0
switch inputUnit {
case 0:
return metric
case 1:
return metric * 10
case 2:
return metric * 1000
case 3:
return metric * 1_000_000
default:
return 0
}
}
// Convert base unit into relevant imperial measurement.
var imperialConversion: Measurement<UnitLength> {
let imperial = metricConversion
let distance = Measurement(value: imperial, unit: UnitLength.millimeters)
let inches = distance.converted(to: UnitLength.inches)
let feet = distance.converted(to: UnitLength.feet)
let yards = distance.converted(to: UnitLength.yards)
let miles = distance.converted(to: UnitLength.miles)
switch outputUnit {
case 0:
return inches
case 1:
return feet
case 2:
return yards
case 3:
return miles
default:
return distance
}
}
var body: some View {
NavigationView {
Form {
Section(header: Text("Metric Number")) {
TextField("Input Number Here", text: $inputNumber)
.keyboardType(.decimalPad)
}
Section(header: Text("Imperial Number")) {
Text("\(imperialConversion.description)")
}
Section(header: Text("Select Input Unit")) {
Picker("Input", selection: $inputUnit) {
// Use a ForEach to count through all the options in the the array, converting each one into a text view.
ForEach(0 ..< inputUnits.count) {
Text("\(self.inputUnits[$0])")
}
}
.pickerStyle(SegmentedPickerStyle())
}
Section(header: Text("Select Output Unit")) {
Picker("Input", selection: $outputUnit) {
// Use a ForEach to count through all the options in the array, converting each one into a text view.
ForEach(0 ..< outputUnits.count) {
Text("\(self.outputUnits[$0])")
}
}
.pickerStyle(SegmentedPickerStyle())
}
}
.navigationBarTitle("Measurement Converter", displayMode: .inline)
}
}
}
|
|
@kivikatz
I'm also going through Day 19 "Challenge" today and was struggling to do a time converter app. I appreaciate you posting your sample code because it taught me several things that weren't explained in the previous project.
Caleb
|
|
HI @kivikatz
I'm a beginer in Swift/SwiftUI as well (i'm on day 34 challenge only) so maybe my solution isn't the better :-)
But I had the same questions as you when I did this day 19 challenge, so I hope my answer will help you.
To Display the converted value, you need to call the "value" property of your converted instance :
Ex:
// with fromUnit as UnitLength.millimeters
// and toUnit as UnitLength.inches
var convertedValue: Double {
let userValue = Double(value) ?? 0
let measure = Measurement(value: userValue, unit: fromUnit)
return measure.converted(to: toUnit).value
}
// in your Text field
// %.g to avoid non needed 0
Text("\(convertedValue, specifier: "%g")")
//or %.2f to get x.xx value
Text("\(convertedValue, specifier: "%.2f")")
|
|
Hi guys,I'm in the challenge too and I would love to learn how you would improve my code
does the code look good for you?
import SwiftUI
struct ContentView: View {
@State private var inputUnit = ""
private let units = ["Meters", "Kilometers", "Feet", "Yards", "Miles"]
@State private var medInicial = 0
@State private var medFinal = 2
private var conversion: Double {
let unitToConvert = Double(inputUnit) ?? 0
if medInicial == 0 { //Meters
switch (medFinal) {
case 1:
// m -> km
return unitToConvert/1000
case 2:
// m -> ft
return unitToConvert*3.281
case 3:
// m -> yd
return unitToConvert*1.094
case 4:
// m -> miles
return unitToConvert/1609
default:
// m -> m
return unitToConvert
}
} else if medInicial == 1 { //Kilometers
switch (medFinal) {
case 0:
// km -> m
return unitToConvert*1000
case 2:
// km -> ft
return unitToConvert*3281
case 3:
// km -> yd
return unitToConvert*1094
case 4:
// km -> miles
return unitToConvert/1.609
default:
// km -> km
return unitToConvert
}
}else if medInicial == 2 { //Feet
switch (medFinal) {
case 0:
// ft -> m
return unitToConvert/3.281
case 1:
// ft -> km
return unitToConvert/3281
case 3:
// ft -> yd
return unitToConvert/3
case 4:
// ft -> miles
return unitToConvert/5280
default:
// ft -> ft
return unitToConvert
}
} else if medInicial == 3 { //Yards
switch (medFinal) {
case 0:
// yd -> m
return unitToConvert/1.094
case 1:
// yd -> km
return unitToConvert/1094
case 2:
// yd -> ft
return unitToConvert*3
case 4:
// yd -> mi
return unitToConvert/1760
default:
// yd -> yd
return unitToConvert
}
} else if medInicial == 4 { //Miles
switch (medFinal) {
case 0:
// mi -> m
return unitToConvert*1609
case 1:
// mi -> km
return unitToConvert*1.609
case 2:
// mi -> ft
return unitToConvert*5280
case 4:
// mi -> miles
return unitToConvert*1760
default:
// mi -> mi
return unitToConvert
}
}
return unitToConvert
}
var body: some View {
NavigationView {
Form {
Section(header: Text("Input")) {
TextField("Input Number Here", text: $inputUnit)
Picker("Input Unit", selection: $medInicial) {
ForEach(0..<units.count) {
Text("\(self.units[$0])")
}
}
.pickerStyle(SegmentedPickerStyle() )
}
Section(header: Text("Output")) {
Picker("Output Unit", selection: $medFinal) {
ForEach(0..<units.count) {
Text("\(self.units[$0])")
}
}
.pickerStyle(SegmentedPickerStyle() )
Text("\(conversion, specifier: "%.4g")")
}
}.navigationBarTitle("Length Converter")
}
}
}
|
|
Hey guys,
I was looking for some help and after I got there myself, I figured I'd post my code to solve this first challenge. I thought about using switches to run through the math. Then I reread the challenge and tried to convert the input to inches (I'm in the US). Of course cm is smaller than inches, so the math logic is a little bit of a pain and didn't know how to use if else statements within the var finalNumber. Then I went to mm as Paul said, which worked except going from miles to cm is too small a number to display as a double with 5 decimal points. Finally I converted the input to cm, then cm to any of the output units. 1 challenge down, many to go!
import SwiftUI
struct ContentView: View {
@State private var inputText = ""
@State private var outputText = ""
@State private var inputUnit = 0
@State private var outputUnit = 0
let units = ["inches", "feet", "miles", "cm", "meters", "kM"]
let convertToCm = [2.54, 30.48, 160934, 1, 100, 100000]
var finalNumber: Double {
// get inputText into a Double
let inputNumber = Double(inputText) ?? 1
// declare the unit of input
let inputUnitSelected = Double(convertToCm[inputUnit])
// multiply down to cmUnit
let cmUnit = inputNumber * inputUnitSelected
// declare the unit of output
let outputUnitSelection = Double(convertToCm[outputUnit])
// multiply up to newNumber
let newNumber = cmUnit / outputUnitSelection
return newNumber
}
var body: some View {
NavigationView {
Form {
Section {
TextField("Enter Your Number To Convert", text: $inputText)
.keyboardType(.decimalPad)
Picker("Input Unit", selection: $inputUnit) {
ForEach(0 ..< units.count) {
Text("\(self.units[$0])")
}
}
.pickerStyle(SegmentedPickerStyle())
}
Section(header: Text("Your convered number")) {
if finalNumber > 10 {
Text("\(finalNumber, specifier: "%.2f")")
} else {
Text("\(finalNumber)")
}
Picker("Output Unit", selection: $outputUnit) {
ForEach(0 ..< units.count) {
Text("\(self.units[$0])")
}
}
.pickerStyle(SegmentedPickerStyle())
}
}
.navigationBarTitle("I'll Convert You!")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
|