Please note, this blog entry is from a previous course. You might want to check out the current one.
Add two new buttons to your Calculator’s keypad: →M and M. These 2 buttons will set and get (respectively) a variable in the CalculatorBrain called M.
- →M sets the value of the variable M in the brain to the current value of the display (if any)
- →M should not perform an automatic ↲ (though it should reset “user is in the middle of typing a number”)
- Touching M should push an M variable (not the value of M) onto the CalculatorBrain
- Touching either button should show the evaluation of the brain (i.e. the result of evaluate()) in the display
- →M and M are Controller mechanics, not Model mechanics (though they both use the Model mechanic of variables).
- This is not a very great “memory” button on our Calculator, but it’s good for testing whether our variable function implemented above is working properly. Examples …
7 M + √ ⇒ description is √(7+M), display is blank because M is not set
9 →M ⇒ display now shows 4 (the square root of 16), description is still √(7+M)
14 + ⇒ display now shows 18, description is now √(7+M)+14
Rename the two remaining blank buttons in storyboard and link them to actions in the view controller:
To keep the actions generic extract the last character from the button title (“M”), and if there is a valid value store it in the variable values of the calculator brain. Evaluate the brain and finally reset “user is in the middle of typing a number”.
@IBAction func storeVariable(sender: UIButton) { if let variable = last(sender.currentTitle!) { if displayValue != nil { brain.variableValues["\(variable)"] = displayValue if let result = brain.evaluate() { displayValue = result } else { displayValue = nil } } } userIsInTheMiddleOfTypingANumber = false }
Before pushing the variable, check if the “user is in the middle of typing a number” and push that number if necessary – note this is an implicit requirement provided by the examples of item f above.
Then push the variable – like above we get the variable name from the button title – and set its result:
@IBAction func pushVariable(sender: UIButton) { if userIsInTheMiddleOfTypingANumber { enter() } if let result = brain.pushOperand(sender.currentTitle!) { displayValue = result } else { displayValue = nil } }
Two additional minor changes remain. Before we displayed “0” if nothing has happened yet, or a result does not compute. Change that to to display a space character, once in viewDidLoad and once in the setter of the display value:
display.text = " "
The complete code for the task #9 is available on GitHub.














Can I just set function storeVariable as below?
@IBAction func storeVariable(sender: UIButton) {
if displayValue != nil {
brain.variableValues["M"] = displayValue
if let result = brain.evaluate() {
displayValue = result
} else {
displayValue = nil
}
}
userIsInTheMiddleOfTypingANumber = false
}
Of course, but then you would have the magic constant “M” in your code … what if you want to change it “A”, or add additional variables “B” and “C” … ?
Since
displayValue
is an Optional there is no need to unwrap the result from evaluate() before assigning it todisplayValue
. Just write:displayValue = brain.evaluate()
true
If you’re using Swift 2.0, you’ll need to replace the above line:
if let variable = last(sender.currentTitle!) {
…
with:
if let variable = sender.currentTitle!.characters.last {
…
or it won’t work.
@Martin Mandl: Huge thanks for all your help, btw…