UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: Day 19 Challenge - Unit Conversion

Forums > 100 Days of SwiftUI

Hi,

I am completely new to the world of programming and have been following Pauls SwiftUI course. I have managed to complete the first challenge and create a temperature unit conversion app.

The code isn't very pretty and there are lots of if else in order to convert but it seems to work fine.

I have run in to a problem though which I am wondering if there is a solution.

Currently the output text box will display the calculation before the input value is entered. For example:

If Celcius is selected as input and Kelvin as output, 273.15 is displayed if there is no input value.

Is there a way to stop this? Please see the code below.

 @State private var inputUnit = 0
    @State private var outputUnit = 0
    @State private var inputNumber = ""

    let unit = ["Celcius", "Farenheit", "Kelvin"]

    var conversion: Double {

        var conversionResult: Double = 0
        let inputDouble = Double(inputNumber) ?? 0

           // Convert C
        if inputUnit == 0 && outputUnit == 1 {
                 conversionResult = inputDouble * 1.8 + 32
        } else { if inputUnit == 0 && outputUnit == 2 {
                conversionResult = inputDouble + 273.15
        } else { if inputUnit == 0 && outputUnit == 0 {
                 conversionResult = inputDouble
            // Convert F
        } else { if inputUnit == 1 && outputUnit == 0 {
            conversionResult = (inputDouble - 32) / 1.8
        } else { if inputUnit == 1 && outputUnit == 1 {
                 conversionResult = inputDouble
        } else { if inputUnit == 1 && outputUnit == 2 {
            conversionResult = (inputDouble - 32) * 5 / 9 + 273.15
            // Convert K
        } else { if inputUnit == 2 && outputUnit == 0 {
            conversionResult = inputDouble - 273.15
        } else { if inputUnit == 2 && outputUnit == 1 {
            conversionResult = (inputDouble - 273.15) * 9 / 5 + 32
        } else { if inputUnit == 2 && outputUnit == 2 {
            conversionResult = inputDouble
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return conversionResult
    }
Section(header: Text("Converted Value")) {
                Text("\(conversion, specifier: "%.2f")")

Any help is much appreciated!

2      

The reason why it shows the calculated output amount is that your inputDouble is default to 0. If you put a guard let then until a number is type then output will show0

eg

var conversion: Double {
    guard let inputDouble = Double(inputNumber) else {
        return 0
    }

    var conversionResult: Double = 0
    // Convert C
    if inputUnit == 0 && outputUnit == 1 {
        conversionResult = inputDouble * 1.8 + 32
    } else if inputUnit == 0 && outputUnit == 2 {
        conversionResult = inputDouble + 273.15
    } else if inputUnit == 0 && outputUnit == 0 {
        conversionResult = inputDouble
        // Convert F
    } else if inputUnit == 1 && outputUnit == 0 {
        conversionResult = (inputDouble - 32) / 1.8
    } else if inputUnit == 1 && outputUnit == 1 {
        conversionResult = inputDouble
    } else if inputUnit == 1 && outputUnit == 2 {
        conversionResult = (inputDouble - 32) * 5 / 9 + 273.15
        // Convert K
    } else if inputUnit == 2 && outputUnit == 0 {
        conversionResult = inputDouble - 273.15
    } else if inputUnit == 2 && outputUnit == 1 {
        conversionResult = (inputDouble - 273.15) * 9 / 5 + 32
    } else if inputUnit == 2 && outputUnit == 2 {
        conversionResult = inputDouble
    }

    return conversionResult
}

PS when else if not else { if

2      

however I would use switch statements

Use enum for clarity

enum TempType: String, CaseIterable {
    case celsius = "Celsius"
    case fahrenheit = "Fahrenheit"
    case kelvin = "Kelvin"
}

Convert to lowest common denominator EG Kelvin

struct ContentView: View {
    @State private var inputUnit: TempType = .celsius
    @State private var outputUnit: TempType = .celsius
    @State private var input = ""

    var conversion: Double {
        guard let inputAmount = Double(input) else { return 0 }
        var conversionInput = 0.0
        var conversionResult = 0.0

        switch inputUnit {
        case .celsius:
            conversionInput = inputAmount + 273.15
        case .fahrenheit:
            conversionInput = (inputAmount - 32) * 5 / 9 + 273.15
        case .kelvin:
            conversionInput = inputAmount
        }

        switch outputUnit {
        case .celsius:
            conversionResult = conversionInput - 273.15
        case .fahrenheit:
            conversionResult = ((conversionInput - 273.15) * 9 / 5) + 32
        case .kelvin:
            conversionResult = conversionInput
        }

        return conversionResult
    }

    var body: some View {
        Form {
            Section(header: Text("Input Amount")) {
                TextField("Enter Amount", text: $input)
                Picker("Input Amount", selection: $inputUnit) {
                    ForEach(TempType.allCases, id: \.self) {
                        Text($0.rawValue)
                    }
                }
                .pickerStyle(SegmentedPickerStyle())
            }

            Section(header: Text("Result")) {
                Picker("Input Amount", selection: $outputUnit) {
                    ForEach(TempType.allCases, id: \.self) {
                        Text($0.rawValue)
                    }
                }
                .pickerStyle(SegmentedPickerStyle())

                Text("\(conversion, specifier: "%.2f")")
            }
        }
    }
}

3      

That's awesome Nigel. And thank you for posting a more elegant solution than my messy code! Still so much to learn.

Craig

2      

Craig. I was impressed with your logic (as you are only on Day 19) but when you come to use alot of if statements then you can look at switch statements. I just put it in so you can see there is different ways to code (there more then one way to skin a c..ode)

Just a couple of pointers on your code. Look at name of variable etc and try to make them "read" natural (this is hard sometimes) rather then putting Double, ( i know you will see things like numberString for a number that is a String but if the variable is a number(Double, Int etc) then just put a name.

When you put comments give details. eg

// Convert to Kelvin from Celsius

Keep up the good work and happy coding

2      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

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

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

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.