COMP 1601 2021W Tutorial 2 Name: Student ID: Collaborators: A1. If you get rid of the _ from the declaration of formatConversion, you'd have to change all callso to formatConversion to add from: before the argument because without the underscore the name of function arguments must be specified when calling them. This happens on line 27 of main.swift and line 47 of ContentView.swift. A2. The "in to cm" is coded differently in that it is declared as a function (with func) rather than as a closure. To make it the same as the others you would remove the separate declaration and instead change the lines of conversions to something like this: "inch to cm": Converter("inches", "centimeters", {inch in return 2.54 * inch}) A3. The init method is called whenever Converter() is called (it is the constructor of the struct). So, it is called for each value in the conversions dictionary (lines 29-39). A4. No, it is not necessary as if you remove it the code still compiles. The compiler can infer the types of the keys and values of conversions by looking at its values. A5. Just add the follow entry to the conversion dictionary: "mi to km": Converter("miles", "kilometers", {miles in return 1.609344 * miles} B1. convAvail is of type [String], an array of strings. B2. The i+1 is to make the printed menu have entries starting at 1 rather than 0. (The entered number is converted back by the c-1 on line 15.) B3. We can change line 27 and 28 to call convert directly and build a custom string: if let res = conv.convert(v) { print("Boss, I think \(v) \(conv.convFrom) is \(res) \(conv.convTo)!") } B4. The test on line 25 is there because a user could just hit return and not enter anything. The test on line 26 is necessary because the user may not have entered a number. C1. Yes you can. It works fine. Move the body of the views in to replace the view calls. The only code changes required are changing the fromString's to fromS's. struct ContentView: View { @State var convMode: String? = nil @State var fromS = "" var body: some View { VStack{ let availConversions = [String](conversions.keys) Menu("Conversions menu") { ForEach(availConversions, id: \.self) { conversion in Button(conversion, action: { convMode = conversion fromS = "" }) } } Spacer() if let mode = convMode { let conv = conversions[mode]! TextField("Enter \(conv.convFrom)", text: $fromS).padding() Spacer() if let from = Double(fromS) { Text(conv.formatConversion(from: from)) } } else { Text("Please select a conversion") Text("type from the menu above.") } Spacer() Spacer() } } } C2. The ! is to override the optional type, i.e., to insist to the compiler that the value won't be nil. Instead, we can test the value to make sure. Replace lines 43 and 44 with the following: if let conv = conversions[mode] { TextField("Enter \(conv.convFrom)", text: $fromString) } C3. It was very easy to add a menu. Just copy lines 10 and 11 (the call to ConvMenu) and insert the copy between lines 16 and 17 (or, 15 and 16 if you don't want it to be at the very bottom of the screen). C4. Just remove line 31. With this removed, fromString won't be reset when a menu item is chosen and so old values will be preserved. C5. The ForEach() could not have been used in main because it is specific to SwiftUI. There is a forEach that could have been used instead of a for loop, but it only takes a closure argument, it doesn't take a closure and id argument (and it doesn't return a View).