0
1
00:00:00,740 --> 00:00:01,080
All right.
1

2
00:00:01,080 --> 00:00:05,190
So you should have downloaded and unzipped or git cloned
2

3
00:00:05,220 --> 00:00:12,040
the calendar project to your desktop, and we're going to go ahead and open it up inside Xcode.
3

4
00:00:12,300 --> 00:00:18,380
So first things first, I just want to show you around the Main.storyboard that I've created here.
4

5
00:00:18,600 --> 00:00:23,820
Now, you'll notice that the design looks a little bit different from the one that we ended up with at
5

6
00:00:23,820 --> 00:00:25,950
the end of the Auto Layout module.
6

7
00:00:26,130 --> 00:00:31,320
And that's because I added a few more modifications just to make it look a little bit more realistic
7

8
00:00:31,680 --> 00:00:36,310
and more similar to the version of calculator that we've got on the Mac.
8

9
00:00:36,330 --> 00:00:44,030
So a couple of changes that I made are, firstly, I've reduced the space between all of the items inside our StackView.
9

10
00:00:44,070 --> 00:00:49,770
So when you click on any of these StackViews, you can see that the spacing is only one point between all
10

11
00:00:49,770 --> 00:00:50,970
of these gaps.
11

12
00:00:50,970 --> 00:00:57,780
I've also made the background view black so that these gaps show up as lines outlining each button for
12

13
00:00:57,780 --> 00:00:58,420
us.
13

14
00:00:58,720 --> 00:01:06,390
And I've also split up the bottom part by placing these two items in their own stack view, and then stacking
14

15
00:01:06,390 --> 00:01:12,330
that along with the 0 into another vertical stack, so now it distributes equally.
15

16
00:01:12,330 --> 00:01:18,210
And I've also changed the font to a thin font at 50 points and some of these other ones a little bit
16

17
00:01:18,210 --> 00:01:21,630
bigger as well, a system 30, for example.
17

18
00:01:21,630 --> 00:01:28,560
So now that we've taken a look at the design part, it's useful to take a look at what these parts are
18

19
00:01:28,560 --> 00:01:29,620
all linked to.
19

20
00:01:29,670 --> 00:01:33,310
So I've already created IBOutlets and IBActions.
20

21
00:01:33,360 --> 00:01:39,240
So the only outlet that we've got, currently, is the one that's linked to the displayLabel which is this
21

22
00:01:39,240 --> 00:01:45,330
one up here, and this displayLabel is going to be the one that's going to show up our results of our
22

23
00:01:45,330 --> 00:01:50,400
calculations, as well as the numbers that the user types into the keypad.
23

24
00:01:50,400 --> 00:01:52,380
Now, there's two IBActions.
24

25
00:01:52,470 --> 00:01:59,420
One of these IBActions are linked to all of the calculation buttons and it's called calcButtonPressed.
25

26
00:01:59,580 --> 00:02:05,310
And the other one is linked up to all of the number or the digit-related buttons,
26

27
00:02:05,430 --> 00:02:08,010
and it's called numButtonPressed.
27

28
00:02:08,010 --> 00:02:14,710
And we're going to be using these two methods in order to implement the functionality of our calculator,
28

29
00:02:14,850 --> 00:02:19,440
but it's important that you realize which buttons are linked to which method.
29

30
00:02:19,470 --> 00:02:21,870
So just familiarize yourself with that.
30

31
00:02:22,050 --> 00:02:27,230
So once you're ready, we can crack on and start building our calculator.
31

32
00:02:27,540 --> 00:02:34,530
So first things first, we want the user to be able to tap on any of these numbers and have it show up
32

33
00:02:34,650 --> 00:02:37,290
up here in the displayLabel.
33

34
00:02:37,290 --> 00:02:43,170
So as I mentioned before, the numButtonPressed is the action that's responsible to a tap on any of
34

35
00:02:43,170 --> 00:02:44,120
these buttons.
35

36
00:02:44,130 --> 00:02:48,950
So this is what should happen when a number is entered into the keypad.
36

37
00:02:49,140 --> 00:02:52,370
And this is also where we're going to add our code.
37

38
00:02:52,530 --> 00:02:58,740
So previously, in the Xylophone app, if you remember, we also had multiple buttons linked up to the same
38

39
00:02:58,950 --> 00:03:05,450
IBAction, and in that case, what we did was we gave each of these buttons a different Tag value.
39

40
00:03:05,760 --> 00:03:12,360
And by looking at what the Tag value of the sender was, we figured out which button was tapped on.
40

41
00:03:12,360 --> 00:03:19,200
Now, that's a little bit manual, and it involves you having to edit the tags manually one by one which
41

42
00:03:19,200 --> 00:03:20,630
is a bit of a pain.
42

43
00:03:20,640 --> 00:03:27,630
So as I always say, programmers are lazy, so what can we do that makes it a little bit easier and less
43

44
00:03:27,630 --> 00:03:28,410
manual?
44

45
00:03:28,410 --> 00:03:33,800
So I want to know the identity of the button that was tapped.
45

46
00:03:33,840 --> 00:03:38,320
And I know that that information is stored inside this object called sender.
46

47
00:03:38,640 --> 00:03:44,030
Now, the sender has a whole bunch of different properties, such as what is the background color,
47

48
00:03:44,040 --> 00:03:49,020
well, in this case, it's blue, or what is the size of the button, for example.
48

49
00:03:49,100 --> 00:03:55,860
Now, you can also see that these different buttons already have a title, right?
49

50
00:03:55,860 --> 00:03:58,090
They already have some text in them.
50

51
00:03:58,080 --> 00:04:05,070
And if I could just figure out what the text was of the button that triggered the IBAction, then that will
51

52
00:04:05,070 --> 00:04:09,660
be really helpful for me to implement my calculator functionality.
52

53
00:04:09,660 --> 00:04:17,790
So if we tap into the sender object and we use the dot to find all of its properties, even if you just
53

54
00:04:17,790 --> 00:04:25,170
start searching randomly for what you think could be the name of the property, Xcode is very helpful
54

55
00:04:25,200 --> 00:04:29,280
in pulling up all of the related properties and methods.
55

56
00:04:29,280 --> 00:04:33,980
So in my case, I kind of want to know what the title of that button is.
56

57
00:04:33,990 --> 00:04:40,040
So I might say sender.title and you can see that it's giving me a whole bunch of suggestions.
57

58
00:04:40,140 --> 00:04:44,960
Do I want the titleLabel? Do I want the title for UIControl.State?
58

59
00:04:44,970 --> 00:04:52,470
And you can see which ones are variables, which ones are methods. Or do I want the titleColor, titleRect?
59

60
00:04:52,650 --> 00:04:56,410
Now, you can see that there's two contenders in this case.
60

61
00:04:56,460 --> 00:05:03,950
One is the tie to a label, and this as it describes down here, is a view that displays the value of the
61

62
00:05:03,950 --> 00:05:06,620
current title property for a button.
62

63
00:05:06,650 --> 00:05:08,980
So we could go through it this way.
63

64
00:05:09,050 --> 00:05:12,450
But there's actually even better one if you scroll through this list.
64

65
00:05:12,620 --> 00:05:18,740
There's this one called current title and the description for this one is the current title that's displayed
65

66
00:05:18,860 --> 00:05:19,680
on the button.
66

67
00:05:19,700 --> 00:05:21,080
Well, that's perfect, right?
67

68
00:05:21,080 --> 00:05:25,910
That's exactly what we need in order to figure out which button was pressed.
68

69
00:05:25,910 --> 00:05:32,150
Now, there's a lot of documentation that you can look up online and you'll find all the help in the world
69

70
00:05:32,180 --> 00:05:35,990
on Stack Overflow and Google and blog posts
70

71
00:05:35,990 --> 00:05:42,680
but there's nothing that is quite as quick and easy as just searching for what you want and just coming
71

72
00:05:42,680 --> 00:05:49,220
up with a name that you think is likely, and then scrolling through that list for a good contender,
72

73
00:05:49,700 --> 00:05:57,220
just as we did here. So in my case, I want to set the display label's text to the current title of the button,
73

74
00:05:57,230 --> 00:06:01,160
so that means if the user taps 1, I want this to read 1.
74

75
00:06:01,280 --> 00:06:08,120
Now, I can do that by tapping into my IBOutlet displayLabel, and then going into its text property and
75

76
00:06:08,120 --> 00:06:11,360
setting that equal to sender.current title.
76

77
00:06:11,360 --> 00:06:13,970
Now, there's just one problem.
77

78
00:06:13,970 --> 00:06:22,250
If you hold down alt and click on current title, you can see that this is a String question mark,
78

79
00:06:22,340 --> 00:06:24,370
so this is an optional string.
79

80
00:06:24,650 --> 00:06:30,160
And if we read through the discussion, the last sentence says that the value may be nil.
80

81
00:06:30,170 --> 00:06:33,590
Well, what if we had a button that didn't actually have a title?
81

82
00:06:33,710 --> 00:06:37,240
Well, in that case, sender.currentTitle will be nil
82

83
00:06:37,460 --> 00:06:40,770
and this line of code will crash your app.
83

84
00:06:40,820 --> 00:06:45,290
Now, another neat thing that you can see now that you know all about computed properties is that you
84

85
00:06:45,290 --> 00:06:50,300
can see that this currenTitle property is a get-only property,
85

86
00:06:50,420 --> 00:06:51,940
so it's read-only.
86

87
00:06:51,950 --> 00:06:59,780
So that means we can't, for example, say, sender.currentTitle equals something, something, that doesn't
87

88
00:06:59,780 --> 00:07:07,450
work because as it suggests currentTitle is the currentTitle that's in the button, and it doesn't let
88

89
00:07:07,460 --> 00:07:11,350
you to give it a new value by setting it.
89

90
00:07:11,510 --> 00:07:18,110
And this is achieved through making currentTitle a computed property that only has a get defined and
90

91
00:07:18,110 --> 00:07:19,250
no set.
91

92
00:07:19,250 --> 00:07:24,770
So here's a little bit of a practical example of what we've been learning about in the last module.
92

93
00:07:24,770 --> 00:07:28,980
Now, in our case, I don't really want this line to crash.
93

94
00:07:29,150 --> 00:07:37,170
So what I want to do is I'm going to use a "if let" and I'm going to call it a numValue,
94

95
00:07:37,430 --> 00:07:39,610
so the number value.
95

96
00:07:39,980 --> 00:07:43,640
And I'm going to set that to equal the sender.currentTitle.
96

97
00:07:43,640 --> 00:07:48,260
And if this sender.currentTitle happens to be not nil,
97

98
00:07:48,260 --> 00:07:57,080
then inside the "if let" is where we're going to set the displayLabel.text to equal to that new
98

99
00:07:57,170 --> 00:08:04,250
unwrapped numValue. And you can see now numValue is just a bog-standard regular string as
99

100
00:08:04,250 --> 00:08:06,190
opposed to an optional string.
100

101
00:08:06,230 --> 00:08:09,740
So we can test our app and see what we get.
101

102
00:08:09,740 --> 00:08:12,850
All right, so here's our simulator on the left here,
102

103
00:08:13,010 --> 00:08:17,330
and I'm going to tap on the 7 and you can see 7 shows up in here.
103

104
00:08:17,510 --> 00:08:22,430
Now, this is just a bit of an issue with our app and I'm sure you can already see it.
104

105
00:08:22,430 --> 00:08:25,130
Now, what if I wanted two digits?
105

106
00:08:25,130 --> 00:08:32,000
Well, I can't at the moment. I can only put in one digit because I'm setting the displayLabel.text
106

107
00:08:32,090 --> 00:08:38,120
to equal whatever button was pressed through these three lines of code.
107

108
00:08:38,150 --> 00:08:39,970
So here's a challenge.
108

109
00:08:39,980 --> 00:08:48,260
Can you figure out a way of appending the numbers that the user keeps on tapping on, so that inside the
109

110
00:08:48,290 --> 00:08:52,790
displayLabel, we display the entire number that they wanted to put in?
110

111
00:08:52,790 --> 00:08:58,810
So for example, if I wanted to type 150, I should be able to see 150 show up up here.
111

112
00:08:58,970 --> 00:09:03,610
And to only set it back to nil or allow a new number to be entered
112

113
00:09:03,620 --> 00:09:07,100
when I click on any of these other buttons.
113

114
00:09:07,130 --> 00:09:11,360
So this is pretty much classic calculator functionality.
114

115
00:09:11,360 --> 00:09:13,850
You don't need me to go through it any more than that.
115

116
00:09:13,850 --> 00:09:17,550
So pause the video and see if you can complete that challenge.
116

117
00:09:20,420 --> 00:09:20,750
All right.
117

118
00:09:20,750 --> 00:09:28,580
So, basically, what we need to do is to append each of these numValues to each other and display it
118

119
00:09:28,640 --> 00:09:34,530
in the displayLabel until the user taps on one of these calculate buttons.
119

120
00:09:34,550 --> 00:09:40,960
So a typical case would be, say, for example, I'm trying to type in 150 plus 3,
120

121
00:09:41,000 --> 00:09:41,340
right?
121

122
00:09:41,450 --> 00:09:48,940
So when I type plus, then I can clear the 150, and I can start from scratch on the 3.
122

123
00:09:48,950 --> 00:09:56,000
So in order to do that, I need to have some sort of property that keeps hold of whether if the user is
123

124
00:09:56,000 --> 00:09:58,340
done typing the number.
124

125
00:09:58,670 --> 00:10:03,350
So let's go up here, and just below IBOutlet,
125

126
00:10:03,350 --> 00:10:09,960
let's create a new variable and let's call it isFinishedTypingNumber.
126

127
00:10:09,980 --> 00:10:15,290
This is a little bit wordy but, hey, we've got Xcode autosuggesting everything, so we don't have to type
127

128
00:10:15,290 --> 00:10:16,020
everything out,
128

129
00:10:16,160 --> 00:10:18,530
so why not make it super clear.
129

130
00:10:18,680 --> 00:10:25,900
So isFinishedTypingNumber is going to be a Boolean and it's going to start off in life as being true.
130

131
00:10:25,940 --> 00:10:31,630
So when we first start up our app, then isFinishedTypingNumber is going to be true.
131

132
00:10:31,850 --> 00:10:41,420
So, now we can go inside our numButtonPressed and we can check to see if isFinishedTypingNumber
132

133
00:10:42,050 --> 00:10:43,940
is equal to true.
133

134
00:10:43,940 --> 00:10:50,060
You can either use this full syntax where you have it checking with a double equals or you can simply
134

135
00:10:50,270 --> 00:10:57,310
just delete that and everything between the "if" keyword and the open curly brace is evaluated.
135

136
00:10:57,470 --> 00:11:02,030
And if it is true, then this block will be carried out,
136

137
00:11:02,210 --> 00:11:03,910
otherwise, it will not.
137

138
00:11:03,920 --> 00:11:09,730
So inside here if isFinishedTypingNumber is true, then that means we're just starting out,
138

139
00:11:09,890 --> 00:11:15,800
and the number in the label is probably 0 or we're just starting out with a new number that we want
139

140
00:11:15,800 --> 00:11:16,480
to type.
140

141
00:11:16,670 --> 00:11:23,450
So in that case, we do want to set the displayLabel.text to equal the numValue, so the value
141

142
00:11:23,450 --> 00:11:25,410
of the button that got pressed.
142

143
00:11:25,430 --> 00:11:33,470
So when I first start out the app, the display label says 0 and isFinishedTypingNumber is going
143

144
00:11:33,470 --> 00:11:34,950
to be initialized to true.
144

145
00:11:35,060 --> 00:11:41,600
So in this case, when I press one of the buttons, then that is the value that is going to go into this
145

146
00:11:41,690 --> 00:11:42,960
UILabel.
146

147
00:11:42,980 --> 00:11:47,510
Now, once we've set a number into the label,
147

148
00:11:47,570 --> 00:11:50,760
so the first number is showing up in there,
148

149
00:11:51,020 --> 00:11:59,510
then we have to switch this isfinishedTypingNumber to false, because we are not done typing the number,
149

150
00:11:59,510 --> 00:12:06,980
right? We've just typed in the first number, and until I press one of these buttons, the orange or the
150

151
00:12:06,980 --> 00:12:13,970
gray buttons, I want my calculator to accumulate all the numbers, so that I can type a number that is
151

152
00:12:13,970 --> 00:12:15,470
more than one digit.
152

153
00:12:15,470 --> 00:12:18,200
For example, I want to be able to type 150.
153

154
00:12:18,560 --> 00:12:22,060
So inside here, we can define our else case.
154

155
00:12:22,100 --> 00:12:29,720
So namely, when this IBAction is triggered and we are not finished typing number, we've just started typing
155

156
00:12:29,720 --> 00:12:30,400
a number,
156

157
00:12:30,650 --> 00:12:36,390
then we should be able to accumulate the number by appending them to the previous number.
157

158
00:12:36,590 --> 00:12:46,430
So in this case, then we can say displayLabel.text is equal to the current text in the displayLabel,
158

159
00:12:46,790 --> 00:12:52,080
plus, or rather append what is currently the numValue.
159

160
00:12:52,370 --> 00:12:59,360
So what this line of code will do is it will look at the currentTitle of the button that was pressed
160

161
00:12:59,870 --> 00:13:07,300
and it will append that value to what is currently inside the displayLabel here.
161

162
00:13:07,520 --> 00:13:12,710
So if I run this code now, you can see that when I type 1,
162

163
00:13:12,770 --> 00:13:18,390
now at this point isFinishedTypingNumber is set to false.
163

164
00:13:18,410 --> 00:13:25,520
So we're going to go inside this else bracket, and that means that the next button I press will get
164

165
00:13:25,760 --> 00:13:29,690
added or appended to the previous value of the displayLabel,
165

166
00:13:29,690 --> 00:13:38,200
and now I have 15. And if I keep going until 0, I can keep adding numbers and it will continue to append.
166

167
00:13:38,330 --> 00:13:45,620
Now, ideally, when I press any of these buttons, for example, plus, I want to be able to start typing a new
167

168
00:13:45,620 --> 00:13:48,990
number, instead of continuing to append numbers.
168

169
00:13:49,010 --> 00:13:54,490
So in order for that to happen, we have to go into our calcButtonPressed because, remember, this 
169

170
00:13:54,500 --> 00:13:57,520
IBAction is linked to all of the calculation buttons.
170

171
00:13:57,830 --> 00:14:02,930
And here I'm going to set that variable isFinishedTypingNumber to
171

172
00:14:02,990 --> 00:14:03,860
true.
172

173
00:14:04,100 --> 00:14:11,390
Because if I've typed a whole bunch of numbers, and then I press the add button, then I'm pretty much finished
173

174
00:14:11,480 --> 00:14:12,560
typing number, right?
174

175
00:14:12,560 --> 00:14:16,120
I want to type a new number to add to my last number.
175

176
00:14:16,400 --> 00:14:22,540
So, now let's run our app with that minor update. Now, you can see I can type 150,
176

177
00:14:22,550 --> 00:14:29,910
and then when I press any of these buttons, say, plus, then I can add in a new number, 150 plus 250.
177

178
00:14:29,940 --> 00:14:35,320
Now, none of the equal signs or anything else works because we haven't implemented anything in there.
178

179
00:14:35,480 --> 00:14:42,110
But you can see I've already managed to use our variable isFinishedTypingNumber and toggling it state
179

180
00:14:42,230 --> 00:14:47,660
to be able to make my calculator accumulate numbers when I need it to, and to forget about the numbers
180

181
00:14:47,750 --> 00:14:49,320
when I need it to as well.
