NEW: Start my new Ultimate Portfolio App course with a free Hacking with Swift+ trial! >>

Day 19: Challenge Day

Forums > 100 Days of SwiftUI

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)
        }
    }
}

1      

@Caleb  

@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")")

2      

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()
    }
}

   

Hacking with Swift is sponsored by Essential Developer

SPONSORED From January 26th to 31st you can join a FREE crash course for iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a senior developer!

Save your spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.