Implement a UILabel in your UI which shows the sequence of operands and operations that led to (or is leading to if resultIsPending) what is (or “will be” if resultIsPending) showing in the display. If resultIsPending is true, put . . . on the end of the UILabel, else put =. If the userIsInTheMiddleOfTyping, you can leave the UILabel showing whatever was there before the user started typing the number. Examples …
a. touching 7 + would show “7 + …” (with 7 still in the display)
b. 7 + 9 would show “7 + …” (9 in the display)
c. 7 + 9 = would show “7 + 9 =” (16 in the display)
d. 7 + 9 = √ would show “√(7 + 9) =” (4 in the display)
e. 7 + 9 = √ + 2 = would show “√(7 + 9) + 2 =” (6 in the display)
f. 7 + 9 √ would show “7 + √(9) …” (3 in the display)
g. 7 + 9 √ = would show “7 + √(9) =“ (10 in the display)
h. 7 + 9 = + 6 = + 3 = would show “7 + 9 + 6 + 3 =” (25 in the display)
i. 7 + 9 = √ 6 + 3 = would show “6 + 3 =” (9 in the display)
j. 5 + 6 = 7 3 would show “5 + 6 =” (73 in the display)
k. 4 × π = would show “4 × π =“ (12.5663706143592 in the display)
Add the new label in story board above the display label:
If you cannot see it in the image above, have close look, it’s there but I set the default value to ” “.
Connect the new label to an outlet in your view controller:
@IBOutlet weak var descriptionDisplay: UILabel!
The calculator brain returns a not really nicely formated string, because it just prints the Doubles into a string, which results trailing zeros. The model should not really care what your output should look like. That’s the responsibility of the view controller.
To find the trailing zeros, I will use regular expression. I might need this in the future, thus I extended the string class:
extension String { func replace(pattern: String, with replacement: String) -> String { let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive) let range = NSMakeRange(0, self.characters.count) return regex.stringByReplacingMatches(in: self, options: [], range: range, withTemplate: replacement) } }
Use this method to find strings starting with a dot, followed by any number of zeros, which are not followed by another digit or are situated at the end of the string. Because the following operator is part of the found substrings, use this operator to replace the rest of the found substring:
extension String { func beautifyNumbers() -> String { return self.replace(pattern: "\\.0+([^0-9]|$)", with: "$1") } }
Now we are ready to use this helpers to display the description, whenever an operation is performed. Depending if a result is pending add ellipses or the equity sign. If there is nothing to display, show simple space:
@IBAction func performOperation(_ sender: UIButton) { ... if let description = brain.description { descriptionDisplay.text = description.beautifyNumbers() + (brain.resultIsPending ? "…" : "=") } else { descriptionDisplay.text = " " } }
You can use the same method for the display value:
var displayValue: Double { ... set { display.text = String(newValue).beautifyNumbers() } }
And while you are at it, make sure you cannot add multiple zeros without a trailing digit:
@IBAction func touchDigit(_ sender: UIButton) { ... } else { switch digit { case ".": display.text = "0." case "0": if "0" == display.text { return } fallthrough default: display.text = digit } userIsInTheMiddleOfTyping = true } }
The complete code for the assignment #1 task #7 is available on GitHub.