COMP 1601 2021W Assignment 1 Solutions 1. Replace lines 46-48 of ContentView.swift with the following: if let from = Double(fromString) { if let to = conv.convert(from) { Text("\(fromString) \(conv.convFrom) is ") + Text("\(to) \(conv.convTo).").bold() } else { Text("Conversion failed.") } } Note we couldn't use formatConversion(); instead we called convert() directly and generated the string ourselves, bolding only part of the text as shown in Tutorial 1. 2a. Replace the for loop on lines 7-9 with the following: var i = 0 convAvail.forEach({c in i = i+1 print(" \(i). \(c)") }) Note how we have to manually create a loop index using a variable declared outside of the forEach closure. 2b. Change line 22 from: let getConversion = {(_ choice: String) in to: func getConversion(_ choice: String) { 2c. The function getConversion should be changed as follows. One line is changed and two are added, but most of the body gets re-indented. Note that the added print statement would only run if an unknown choice is given. With the way this program is constructed this could never happen; however, later changes could result in an undefined choice. func getConversion(_ choice: String) { if let conv = conversions[choice] { // <--- added an if here and { print("\nEnter \(conv.convFrom): ", terminator: "") if let vs = readLine() { if let v = Double(vs) { let res = conv.formatConversion(v) print(res) return } else { // <--- added an else print("You didn't enter a number!") // <--- added this print } } } else { print("Unknown conversion \(choice)!") } } 2d. First, add a new menu item at the end by inserting this after printing the menu (line 10): print(" \(convAvail.count + 1). Quit") Next, return "Quit" when this option is selected (insert between 16 and 17): print(" \(convAvail.count + 1). Quit") Finally, add a while loop to the last part of the program. Replace lines 36-40 with the following: var done = false while !done { if let choice = getChoice() { if choice != "Quit" { getConversion(choice) print("") } else { print("Goodbye!") done = true } } else { print("You didn't make a valid choice!") } } 3a. First, add a new property to the Converter struct at Conversions:7: var defaultVal: String Then, change init as follows (Conversions, 16-20): init(_ from: String, _ to: String, _ f: @escaping (_ from: Double) -> Double?, _ d: String) { // <--- added to function declaration self.convFrom = from self.convTo = to self.convert = f self.defaultVal = d // <--- added } Finally, add the default values to the conversions (replacing lines 28-40): let conversions: [String: Converter] = ["F to C": Converter("Farenheit", "Celsius", {F in return ((F - 32.0)*(5/9))}, "32.0"), "C to F": Converter("Celsius", "Farenheit", {C in return ((9/5)*C + 32.0)}, "0.0"), "km to mi": Converter("kilometers", "miles", {k in let m = k * 0.6213712 return m }, "88.0"), "inch to cm": Converter("inches", "centimeters", InToCM, "12.0") ] 3b. Replace ContentView:31 with the following: if let c = conversions[conversion] { fromString = c.defaultVal } else { fromString = "" } 3c. Add a new view (around ContentView:55): struct ConvPrompt: View { @Binding var convMode: String? @Binding var fromString: String var body: some View { if let c = convMode { if let conv = conversions[c] { if conv.defaultVal == fromString { Text("Please enter your own number to convert.").italic() } } } } } To add this view, add the following between ContentView:15 and 16 (between the calls to Spacer): ConvPrompt(convMode: $convMode, fromString: $fromS) 3d. The message disappears the moment one character is entered or changed. This means that the new view has to be run on every keypress and every time a new menu item is selected.