0
1
00:00:01,340 --> 00:00:08,660
Now, in the last lesson, we looked at how Swift tuples work. And now we're able to use it inside this
1

2
00:00:08,660 --> 00:00:16,460
"else if" statement to be able to store the first number of the calculation and also the operation of the calculation.
2

3
00:00:16,640 --> 00:00:24,930
So right at the top here, let's create a brand-new variable that is going to be our intermediate calculation.
3

4
00:00:25,010 --> 00:00:33,620
Now, as a challenge, I want you to create this as a tuple that can store a string and a number that corresponds
4

5
00:00:33,710 --> 00:00:37,350
to the first number that the user is going to calculate with,
5

6
00:00:37,640 --> 00:00:40,050
and also the operation.
6

7
00:00:40,160 --> 00:00:46,130
Now, remember, all of the things that we spoke about in the advanced Swift section and try to create this
7

8
00:00:46,130 --> 00:00:50,190
tuple so that it complies with all of the best practice.
8

9
00:00:50,200 --> 00:00:51,790
Pause the video and give it a go.
9

10
00:00:54,240 --> 00:00:54,600
All right.
10

11
00:00:54,600 --> 00:00:57,130
So here's our tuple up here.
11

12
00:00:57,360 --> 00:01:00,480
And we're not going to give it any values up here
12

13
00:01:00,480 --> 00:01:02,450
when we initialize our structure.
13

14
00:01:02,550 --> 00:01:05,470
So we're only going to specify it's data type.
14

15
00:01:05,730 --> 00:01:09,970
And remember, we specify a tuples data type with a set of parentheses.
15

16
00:01:10,290 --> 00:01:15,860
Now, the first item inside our tuple is going to be the first number.
16

17
00:01:16,110 --> 00:01:20,460
So this is going to be a Double and I'm going to call it n1.
17

18
00:01:20,550 --> 00:01:24,900
Now, the second thing we need to store in here is the calculation method.
18

19
00:01:24,930 --> 00:01:29,270
So I'll just call that calcMethod and this is going to be a String.
19

20
00:01:29,280 --> 00:01:32,460
Now, I don't actually have a value for this tuple
20

21
00:01:32,460 --> 00:01:35,860
when I initialize my CalculatorLogic structure,
21

22
00:01:36,210 --> 00:01:41,320
so I have to be able to set it to nil when I create CalculatorLogic.
22

23
00:01:41,460 --> 00:01:44,380
That means I have to turn it into an optional.
23

24
00:01:44,730 --> 00:01:51,010
And I do that by just adding a question mark to the end of the entire type,
24

25
00:01:51,060 --> 00:01:51,630
right?
25

26
00:01:51,660 --> 00:01:57,190
So in this case, the type is a Double and so the question mark goes at the end of the Double.
26

27
00:01:57,420 --> 00:02:01,210
But in this case, the type of the tuple is all of this,
27

28
00:02:01,320 --> 00:02:04,160
and so the question mark goes right at the end.
28

29
00:02:04,180 --> 00:02:07,320
Now, if instead you'd added the question mark here,
29

30
00:02:07,380 --> 00:02:11,770
then that means you can create tuples that may or may not have an n1.
30

31
00:02:11,970 --> 00:02:16,980
And if you created one here, then that means you can create a tuple that may or may not have an n1
31

32
00:02:17,070 --> 00:02:18,200
or a calcMethod.
32

33
00:02:18,360 --> 00:02:19,410
Now, that's not what we want,
33

34
00:02:19,410 --> 00:02:21,070
so we're going to delete those, too,
34

35
00:02:21,180 --> 00:02:24,900
but we're going to keep the entire tuple as an optional.
35

36
00:02:24,900 --> 00:02:32,100
Now, the final thing to consider is, remember, whenever creating global variables to start it out as a private
36

37
00:02:32,190 --> 00:02:39,500
var, that way we prevent other classes from messing withintermediateCalculation and, certainly, no other
37

38
00:02:39,510 --> 00:02:45,070
class or structure actually needs to be able to modify our intermediate calculation.
38

39
00:02:45,090 --> 00:02:50,950
It's a bit of data that we've saved right in the middle of something we're doing inside CalculatorLogic,
39

40
00:02:51,060 --> 00:02:56,220
so we have to defend it from other people accidentally changing or modifying it.
40

41
00:02:56,220 --> 00:02:59,520
So now that that's done, we can head over into this
41

42
00:02:59,520 --> 00:03:06,010
"else if" and we can set our intermediateCalculation, and I'm going to set it equal to a tuple,
42

43
00:03:06,060 --> 00:03:10,810
so a set of parentheses, and then I'm going to tap into n1.
43

44
00:03:10,950 --> 00:03:14,040
Now, I find that Xcode is not great with autosuggest
44

45
00:03:14,040 --> 00:03:15,570
when it comes to tuples,
45

46
00:03:15,570 --> 00:03:17,980
so I like to type it out just manually.
46

47
00:03:18,280 --> 00:03:23,550
Now,  n1 is going to be the number that got passed over with the calculation,
47

48
00:03:23,550 --> 00:03:25,210
so that is equal to n.
48

49
00:03:25,220 --> 00:03:28,480
And then the next thing is the calcMethod.
49

50
00:03:28,530 --> 00:03:34,430
And this is simply going to be the symbol that got passed in when this calcMethod was called.
50

51
00:03:34,500 --> 00:03:39,420
So, now we have set our tuple inside this "else if."
51

52
00:03:39,450 --> 00:03:45,810
So that means when a user taps on a number, and then taps on one of the calcButtons, will pass over
52

53
00:03:45,930 --> 00:03:51,140
the number as well as the calculation method over to our CalculatorLogic.
53

54
00:03:51,360 --> 00:03:53,850
And then it's caught inside here
54

55
00:03:54,030 --> 00:04:01,020
if it was a plus sign that they pressed. aAnd we save that plus sign along with the number inside our
55

56
00:04:01,020 --> 00:04:01,570
tuple.
56

57
00:04:01,590 --> 00:04:05,060
That's called intermediateCalculation for later use.
57

58
00:04:05,070 --> 00:04:11,040
Now, at this point, Xcode, again, tells you that self is immutable because we're inside a struct and
58

59
00:04:11,040 --> 00:04:13,430
we're changing one of the properties here,
59

60
00:04:13,620 --> 00:04:16,880
so therefore, we have to mark this as mutating.
60

61
00:04:17,040 --> 00:04:22,110
So in order to succeed at this challenge, you actually have to have remembered a lot of the things that
61

62
00:04:22,110 --> 00:04:24,180
we discussed in this module.
62

63
00:04:24,210 --> 00:04:30,420
So if any of those things were at all confusing, be sure to have a look back at some of the lessons previously
63

64
00:04:30,720 --> 00:04:37,750
where we discussed access levels or structs and classes and some of the advanced Swift best practice.
64

65
00:04:37,980 --> 00:04:44,240
So, now we have to address what should happen when the user finally presses the equals button.
65

66
00:04:44,490 --> 00:04:51,720
Well, at this point, we should trigger the entire calculation and use what we saved inside the intermediate
66

67
00:04:51,720 --> 00:04:52,620
calculation,
67

68
00:04:52,650 --> 00:04:53,100
right?
68

69
00:04:53,280 --> 00:04:59,280
So let's go ahead and call another method in here which we'll call 
69

70
00:04:59,340 --> 00:05:07,530
performTwoNumberCalculation. And this method is only going to have one input and that is going to be the second
70

71
00:05:07,530 --> 00:05:12,240
number that we're performing the calculation with which is, again, going to be a Double.
71

72
00:05:12,480 --> 00:05:16,200
So that number, in this case, will be, right?
72

73
00:05:16,320 --> 00:05:23,370
Because when the user has pressed the equal sign, then that means we passed in the second number that
73

74
00:05:23,370 --> 00:05:24,240
they tapped on.
74

75
00:05:24,240 --> 00:05:26,250
So let's go back to our calculator.
75

76
00:05:26,460 --> 00:05:34,200
When I press on 5 and then plus, then the calculate method gets triggered, and we fall into this "else if"
76

77
00:05:34,260 --> 00:05:41,490
bracket where we set our tuple intermediateCalculation to equal the first number that I typed which
77

78
00:05:41,490 --> 00:05:46,870
was the 5, and the calcMethod which is this plus symbol.
78

79
00:05:46,920 --> 00:05:53,180
Now, once that's done, that gets saved and stashed away ready for the next number to come in.
79

80
00:05:53,210 --> 00:05:59,060
And at this point, let's say I press on 3, and then I press equals, and I expect an answer
80

81
00:05:59,060 --> 00:06:00,070
at this point.
81

82
00:06:00,080 --> 00:06:06,800
So then the calculate function gets called again and I catch it inside this "else if" statement because
82

83
00:06:06,800 --> 00:06:09,230
the symbol was the equal sign.
83

84
00:06:09,230 --> 00:06:16,490
And then I call a function that will perform the whole calculation passing in the second number that
84

85
00:06:16,490 --> 00:06:21,680
it needed to add to the first one which happened to be 3 in my example.
85

86
00:06:21,680 --> 00:06:32,120
So let's go ahead and create this function called performTwoNumberCalculation and it expects a parameter
86

87
00:06:32,120 --> 00:06:40,480
called n2 which is going to be a Double, and it's going to return a Double as the outputs. And this
87

88
00:06:40,480 --> 00:06:49,070
functionality is internal to our calculator because it performs the second half of the calculation.
88

89
00:06:49,150 --> 00:06:54,460
And so this shouldn't be called by anybody outside this current structure.
89

90
00:06:54,550 --> 00:07:01,560
So we can mark this method as private as well to prevent from any other classes or structs from accidentally
90

91
00:07:01,570 --> 00:07:04,560
calling it because it will surely create an error.
91

92
00:07:04,690 --> 00:07:10,930
But inside this function, we're going to group together all of our intermediate calculation that we saved
92

93
00:07:10,930 --> 00:07:12,020
into our tuple.
93

94
00:07:12,040 --> 00:07:19,510
So because our tuple is an optional, then we have to unwrap it or use optional binding to check to make
94

95
00:07:19,510 --> 00:07:22,400
sure that we definitely actually have values for it.
95

96
00:07:22,600 --> 00:07:28,420
Because if the user simply pressed the equal sign right at the beginning by accident without having
96

97
00:07:28,720 --> 00:07:34,300
any operations specified or any number specified, we don't want our app to crash,
97

98
00:07:34,300 --> 00:07:34,810
right?
98

99
00:07:35,080 --> 00:07:45,400
So let's create an "if let" and let's say that if let n1 =  intermediateCalculation.n1,
99

100
00:07:45,410 --> 00:07:54,700
and then we can do the optional binding calcMethod in the same line by simply adding a comma.
100

101
00:07:54,700 --> 00:08:03,760
So if let n1 = intermediateCalculation.n1, and also let operation equal 
101

102
00:08:03,760 --> 00:08:11,030
intermediateCalculation.calcMethod, then and only then do we perform the code inside this block.
102

103
00:08:11,140 --> 00:08:16,740
So you can see that if I split this code into two lines, we are creating two constants.
103

104
00:08:16,780 --> 00:08:24,010
One is called n1,  one is called operation. and we're creating it by optionally chaining
104

105
00:08:24,010 --> 00:08:25,090
intermediateCalculation.
105

106
00:08:25,100 --> 00:08:30,550
So we're saying if intermediate calculation is not nil, that's what that question mark says,
106

107
00:08:30,780 --> 00:08:37,200
then tap into the n1 value inside it and bind it to this thing called n1.
107

108
00:08:37,540 --> 00:08:43,680
And if intermediateCalculation is not nil, again, grab the calcMethod out of it and assign it to our
108

109
00:08:43,680 --> 00:08:44,950
operation.
109

110
00:08:44,950 --> 00:08:53,400
So now that we've got n1 and operation, both unwrapped as non-optionals, we know that they're definitely not
110

111
00:08:53,430 --> 00:08:54,230
nil,
111

112
00:08:54,410 --> 00:09:03,100
then, in this case, we can complete our calculation. So we can say that if the operation was equal to plus,
112

113
00:09:03,310 --> 00:09:11,060
then in that case, we should return as the output n1 + n2,
113

114
00:09:11,170 --> 00:09:13,790
and that is our addition functionality.
114

115
00:09:13,960 --> 00:09:21,940
So if we have a look back at our "if" statement over here, it doesn't make sense to check for plus, minus,
115

116
00:09:22,030 --> 00:09:27,920
times, multiply, divide over here if we can do it separately over here.
116

117
00:09:28,150 --> 00:09:35,530
So what I'm going to do is I'm going to cut that "else if" statement and I'm going to put it in as an "else"
117

118
00:09:35,620 --> 00:09:36,890
instead.
118

119
00:09:36,910 --> 00:09:45,460
So that means that if the symbol that was passed over was not any of these simple calculations, and it
119

120
00:09:45,460 --> 00:09:53,920
wasn't an equals, then everything else, namely, plus, minus, multiply, divide, should be caught inside here
120

121
00:09:54,760 --> 00:10:01,090
and we should create an intermediateCalculation, because everything else that remains other than these
121

122
00:10:01,090 --> 00:10:08,830
three and this button is going to be a two-number calculation. And we're going to store the actual symbol
122

123
00:10:09,100 --> 00:10:12,610
inside this calcMethod inside our tuple.
123

124
00:10:12,610 --> 00:10:20,380
So once the user presses the next number and they press equals to get the result, then we perform our
124

125
00:10:20,390 --> 00:10:23,580
two-number calculation which is a private function,
125

126
00:10:23,590 --> 00:10:28,330
so it can only be called within this current structure, not from outside,
126

127
00:10:28,540 --> 00:10:35,200
and we complete the operation by checking to see which one needed to be performed, and we return the
127

128
00:10:35,200 --> 00:10:35,810
results.
128

129
00:10:35,860 --> 00:10:40,380
So, now Xcode is telling us that this result is not handled over here.
129

130
00:10:40,540 --> 00:10:41,950
So how should we handle it?
130

131
00:10:42,010 --> 00:10:46,420
Well, of course, we're going to return it as the output of this function,
131

132
00:10:46,420 --> 00:10:46,800
right?
132

133
00:10:46,960 --> 00:10:53,860
So as a challenge, I want you to complete this part where we check for all four different operations:
133

134
00:10:54,190 --> 00:10:59,500
plus, minus, multiply, and divide, and specify what should be returned.
134

135
00:10:59,500 --> 00:11:05,760
Now, because we've got four things that we're checking. It doesn't make sense to have it as an "if" statement.
135

136
00:11:06,010 --> 00:11:12,190
So as a part of the challenge, I want you to change this to a switch statement so you can switch on the
136

137
00:11:12,190 --> 00:11:14,110
operation that needs to be performed.
137

138
00:11:14,110 --> 00:11:18,450
So pause the video and go ahead and give that ago.
138

139
00:11:18,460 --> 00:11:22,880
Okay. So let's change this "if" to a "switch" by changing the keyword.
139

140
00:11:23,000 --> 00:11:30,040
Next, let's delete all of this and all of this, so we have a blank switch statement and we're switching
140

141
00:11:30,040 --> 00:11:31,310
on the operation.
141

142
00:11:31,330 --> 00:11:33,360
So let's address some of those cases.
142

143
00:11:33,610 --> 00:11:42,790
In the case where the operation is equal to a plus sign, then we want to return n1 + n2.
143

144
00:11:46,470 --> 00:11:51,990
But in the case where the operation was a minus sign that the user wanted,
144

145
00:11:51,990 --> 00:11:53,340
then we're going to return
145

146
00:11:53,370 --> 00:11:55,580
n1 - n2.
146

147
00:11:55,620 --> 00:12:02,700
Next, if the case was a multiply, and I recommend that to get the symbol for the multiplication, you head
147

148
00:12:02,700 --> 00:12:09,060
over to the Main.storyboard and just double click on that multiply button to copy the text that's in
148

149
00:12:09,060 --> 00:12:13,660
there because unless the unicode is exactly the same, then this won't work.
149

150
00:12:13,830 --> 00:12:21,900
So, now that we've got the multiply symbol in there, we're going to go ahead and return n1 multiplied
150

151
00:12:21,930 --> 00:12:30,290
by n2. And finally, we're going to address the division which, again, I'm going to copy from over here
151

152
00:12:31,720 --> 00:12:34,210
and I'm going to paste it right here.
152

153
00:12:35,180 --> 00:12:39,210
So the last case, we're going to return n1 / n2.
153

154
00:12:39,860 --> 00:12:44,620
And as with all switch statements, you should always have a default case
154

155
00:12:44,780 --> 00:12:51,650
and this just catches out the cases where your operation that's being passed in does not match any of
155

156
00:12:51,650 --> 00:12:52,400
these.
156

157
00:12:52,490 --> 00:12:55,280
And in our case, that would be very, very weird.
157

158
00:12:55,430 --> 00:13:01,820
But we should still catch it and we should throw a fatal error because it's something that should never
158

159
00:13:01,820 --> 00:13:02,770
really happen.
159

160
00:13:02,780 --> 00:13:11,870
And in this case, we're saying that fatal error, the operation passed in does not match any of the cases.
160

161
00:13:12,170 --> 00:13:14,790
So we'll know what's happening at that point.
161

162
00:13:14,810 --> 00:13:20,450
Now, as you can see, we've had this error screaming at us for a little while now, and it's saying that we're
162

163
00:13:20,450 --> 00:13:25,050
missing a return statement in a function that's expected to return Double.
163

164
00:13:25,100 --> 00:13:28,090
Now, you can see we've got lots of return statements, right?
164

165
00:13:28,100 --> 00:13:30,430
So why are they being so hard on us?
165

166
00:13:30,650 --> 00:13:33,400
Well, it's because we've got these "if lets."
166

167
00:13:33,650 --> 00:13:37,430
And that means that there's cases when these would fail.
167

168
00:13:37,670 --> 00:13:44,600
For example, if the user opens up the app and the first thing they do is they tap on the equal sign,
168

169
00:13:44,900 --> 00:13:50,870
well, in that case, we're going to call our performTwoNumberCalculation and there might not even be
169

170
00:13:50,930 --> 00:13:52,960
an intermediateCalculation yet,
170

171
00:13:53,060 --> 00:13:53,500
right?
171

172
00:13:53,660 --> 00:13:56,090
Just because they tapped on it by accident.
172

173
00:13:56,120 --> 00:13:58,490
Well, in this case, we shouldn't crash the app,
173

174
00:13:58,490 --> 00:14:00,430
we should instead just ignore it.
174

175
00:14:00,440 --> 00:14:02,310
So how do we do that in code?
175

176
00:14:02,450 --> 00:14:08,740
Well, we can simply return nil because there is nothing to perform our two number calculation with.
176

177
00:14:09,110 --> 00:14:10,920
Now, in order to be able to return nil,
177

178
00:14:11,120 --> 00:14:15,580
we can't specify that this method only can output Doubles.
178

179
00:14:15,680 --> 00:14:21,310
It has to be able to output optional Doubles, so that we can return it as a nil.
179

180
00:14:21,320 --> 00:14:27,830
So in this case, if they accidentally tapped on the equal sign, we call performTwoNumberCalculation,
180

181
00:14:28,220 --> 00:14:29,970
this turns into nil,
181

182
00:14:30,020 --> 00:14:34,580
we return nil as the output to our calculateMethod.
182

183
00:14:34,820 --> 00:14:42,290
And over here, we catch that inside this "guard" statement which if you notice is, again, 
183

184
00:14:42,290 --> 00:14:44,550
a fatalError which will crash on app.
184

185
00:14:44,750 --> 00:14:50,870
So this is a really good point to talk about what is the difference between a "guard let" and an "if let"
185

186
00:14:51,020 --> 00:14:56,240
because you'll see them all over the place in a lot of the Swift code out there in the wild.
186

187
00:14:56,330 --> 00:15:01,640
But it's really difficult for an intermediate or beginner's programmer to understand just when to
187

188
00:15:01,640 --> 00:15:03,900
use a "guard let" versus an "if let."
188

189
00:15:04,010 --> 00:15:06,130
And this is a perfect illustration.
189

190
00:15:06,470 --> 00:15:13,550
Well, in this case, when you use a "guard let," it means that you're guarding against something terrible, right?
190

191
00:15:13,580 --> 00:15:15,260
In very few cases,
191

192
00:15:15,260 --> 00:15:18,310
do you expect this "else" to be triggered?
192

193
00:15:18,620 --> 00:15:20,670
That's what a "guard let" is used.
193

194
00:15:20,720 --> 00:15:23,730
We're guarding against really bad things from happening.
194

195
00:15:23,780 --> 00:15:29,180
That should never really happen unless we had some sort of brain freeze and we completely screwed up
195

196
00:15:29,180 --> 00:15:30,440
our code.
196

197
00:15:30,440 --> 00:15:38,030
Now, if we're using an "if let" instead, then that means that we're expecting that nine times out of ten,
197

198
00:15:38,480 --> 00:15:43,660
this will not be nil and we will be able to trigger this block inside here.
198

199
00:15:43,970 --> 00:15:49,950
But we're also accepting that sometimes it might just be nil and that's fine.
199

200
00:15:49,970 --> 00:15:51,710
We don't have to do anything.
200

201
00:15:51,800 --> 00:15:54,540
We can simply ignore those cases.
201

202
00:15:54,560 --> 00:16:02,960
So, now that I've changed that "guard let" to an "if let" and only when I get a non-nil value from my calculation
202

203
00:16:03,290 --> 00:16:05,610
do I update my displayValue,
203

204
00:16:05,780 --> 00:16:12,440
then it means that if I've accidentally-- then that means that if the user has accidentally tapped on the
204

205
00:16:12,440 --> 00:16:18,410
equal sign without any prior numbers or prior operations, then we don't crash our app,
205

206
00:16:18,410 --> 00:16:20,510
instead our code just ignores it.
206

207
00:16:20,510 --> 00:16:27,170
So this is a really good illustration of why you would use "guard let" versus "if let." And I recommend that
207

208
00:16:27,200 --> 00:16:32,990
if you really want to get down to the nitty-gritties of it, try changing it around and run the app and
208

209
00:16:32,990 --> 00:16:35,300
see what happens for yourself,
209

210
00:16:35,390 --> 00:16:38,790
just so that you can get first-hand experience of what I'm saying to you.
210

211
00:16:38,810 --> 00:16:39,130
All right.
211

212
00:16:39,140 --> 00:16:44,600
So our app is pretty much done, the last thing that I'm going to change is just to make the set of "if" statements
212

213
00:16:45,020 --> 00:16:48,530
into a "switch" statement just to clean up our code.
213

214
00:17:01,550 --> 00:17:07,270
So, now we're ready to test our app and see if it works exactly the way we expect it to.
214

215
00:17:07,400 --> 00:17:18,640
So let's try 9 x 2 = 18 + 6 = 24 / 4 = 6.
215

216
00:17:18,650 --> 00:17:20,030
Clear
216

217
00:17:20,090 --> 00:17:23,110
and percentage. Everything works perfectly.
217

218
00:17:23,120 --> 00:17:30,920
Now, there's a lot more that you could do to this calculator by adding extra buttons, extra functionality,
218

219
00:17:30,920 --> 00:17:36,800
you could make it into a graphing calculator if you really wanted to or you could make it more robust
219

220
00:17:36,890 --> 00:17:39,860
and more reliable in terms of the code as well.
220

221
00:17:40,040 --> 00:17:47,090
But I hope that this has been a fun and interesting project. And along the way, we've learned about access
221

222
00:17:47,090 --> 00:17:56,360
levels, struct versus classes, mutating functions, how to use the "self" keyword, internal and external parameter
222

223
00:17:56,360 --> 00:18:06,410
names, swift tuples, and so much more. So as you can see, it's a jam-packed lesson full of advanced concepts.
223

224
00:18:06,440 --> 00:18:12,050
So, now that you've reached this stage in your development journey, it's really important that if there's
224

225
00:18:12,170 --> 00:18:17,360
anything that you don't fully understand, or if there's something that you want to learn more about, then
225

226
00:18:17,360 --> 00:18:23,390
be sure to do some extra reading, and especially by reading through the Swift Programming Language Online
226

227
00:18:23,390 --> 00:18:29,630
Book which you can access at docs.swift,org/swift-book, and you can look through it and
227

228
00:18:29,630 --> 00:18:34,970
read up on the parts that we've covered, and try it out yourself just so that you can make all of the
228

229
00:18:34,970 --> 00:18:37,140
knowledge in the tutorials your own.
229

230
00:18:37,190 --> 00:18:39,890
So it's all from me, Angela@theAppBrewery.
230

231
00:18:40,080 --> 00:18:41,420
So till next time, guys.
