Assignment #2 Task #3

Please note, this blog entry is from a previous course. You might want to check out the current one.

Update the user-interface of your Calculator to test all of the above.

a. Your UI should already have a UILabel which shows what has been sent to the brain. Change it to now always show the latest description of the program currently in the CalculatorBrain using your descriptionOfProgram:method. It should show the description without substituting variable values (obviously, since descriptionOfProgram: does not take a variable value dictionary as an argument).
b. Add a few variable buttons (e.g, x, y, foo). These are buttons that push a variable into the CalculatorBrain.
c. Change your calculator to update its display (as needed) by calling your new runProgram:usingVariableValues: method. The variable values dictionary it passes to this method should be a property in your Controller (let’s call it “testVariableValues”).
d. Add a UILabel to your UI whose contents are determined by iterating through all the variablesUsedInProgram: and displaying each with its current value from testVariableValues. Example display: “x = 5 y = 4.8 foo = 0”.
e. Add a few different “test” buttons which set testVariableValues to some preset testing values. One of them should set testVariableValues to nil. Don’t forget to update the rest of your UI when you change testVariableValues by pressing one of these test buttons. Make sure that your preset values are good edge-cases for testing (we are intentionally not telling you what to use since part of good programming is figuring out how to thoroughly test your application).

To solve #a just remove all occurrences of code where you have manipulated the history label from CalculatorViewControler.m and replace it by

self.history.text = [CalculatorBrain descriptionOfProgram:self.brain.program];

which will render removeEqualSignFromHistory obsolate, so you might want to remove this helper function, too.

For #b we create three new buttons in storyboard and connect them to the action variablePressed:

- (IBAction)variablePressed:(UIButton *)sender {
    [self.brain pushVariable:sender.currentTitle];
    self.history.text = [CalculatorBrain descriptionOfProgram:self.brain.program];

which calls a new method of our model for which we have to create a new API:

- (void)pushVariable:(NSString *)variable {
    [self.programStack addObject:variable];    

For #c we add a new test variable to our controller:

@property (nonatomic, strong) NSDictionary *testVariableValues;

and do not forget to synthesize it

@synthesize testVariableValues = _testVariableValues;

and adjust operationPressed to send our variables to the CalculatorBrain

    double result = [self.brain performOperation:sender.currentTitle 

As the method we used above does not exist yet, we have to create it:

- (double)performOperation:(NSString *)operation 
       usingVariableValues:(NSDictionary *)variableValues
    [self.programStack addObject:operation];
    return [CalculatorBrain runProgram:self.program usingVariableValues:variableValues];    

To show our actual variable values (subtask #d), we create a new label in storyboard and connect it to an outlet called usedVariables

At the moment we would only have to change that output when a variable button is pressed and it would suffice to put appropriate code into variablePressed. But already in the next sub task we would have to call the same piece of code when we populate the variables with actual values. We could create a helper function for that, however, to clean up our code it is much better to create a new function which collects all display functionality, e.g.:

- (void)updateCalculatorView
    NSSet *usedVariables = [CalculatorBrain variablesUsedInProgram:self.brain.program];
    NSString *result = @"";        
    for (NSString *variableName in usedVariables) {
        NSNumber *value = [self.testVariableValues objectForKey:variableName];
        if (!value) value = [NSNumber numberWithInt:0];
        result = [result stringByAppendingFormat:@"%@ = %@   ", variableName, value];
    self.usedVariables.text = result;    
    self.history.text = [CalculatorBrain descriptionOfProgram:self.brain.program];    
    self.display.text = [NSString stringWithFormat:@"%g",
        [CalculatorBrain runProgram:self.brain.program 

Instead of manipulating our label fields separately, we can call this function …

Finally we create test buttons in story board and pobulate our variables in their connected action methods, e.g.:

- (IBAction)testButtonPressed:(UIButton *)sender {
    if ([sender.currentTitle isEqualToString:@"Test 1"]) {
        self.testVariableValues = [NSDictionary dictionaryWithObjectsAndKeys:
            [NSNumber numberWithInt:5], @"x",
            [NSNumber numberWithDouble:-4.8], @"y",
            [NSNumber numberWithInt:0], @"foo",
    if ([sender.currentTitle isEqualToString:@"Test 2"]) {
        self.testVariableValues = nil;        
    [self updateCalculatorView];

Leave a Reply

Your email address will not be published.