0
1
00:00:00,960 --> 00:00:01,260
All right.
1

2
00:00:01,260 --> 00:00:06,900
So, now that we've learned all about struct, it's time to come back to our calculator app and finish the
2

3
00:00:06,900 --> 00:00:08,800
rest of the functionality.
3

4
00:00:08,850 --> 00:00:16,410
So firstly, you would have noticed that I've changed the calculator logic from a class to a struct.
4

5
00:00:16,830 --> 00:00:23,220
And from our knowledge about structs, we now know that we don't actually need an initializer for our structs
5

6
00:00:23,340 --> 00:00:29,820
because we get a free one, right? And Xcode won't give us any errors or complaints because we're now using
6

7
00:00:29,880 --> 00:00:30,960
a struct.
7

8
00:00:30,960 --> 00:00:34,270
Now, there's other things that we can improve in our code as well.
8

9
00:00:34,320 --> 00:00:40,500
If you head over to the ViewController.swift, you can see that at the moment, we're initializing a brand-new
9

10
00:00:40,500 --> 00:00:46,740
CalculatorLogic structure every single time the calc button is pressed.
10

11
00:00:46,740 --> 00:00:48,480
Now, that's pretty inefficient.
11

12
00:00:48,660 --> 00:00:54,410
So let's move this out of the IBAction and let's just move it up here for now.
12

13
00:00:54,690 --> 00:01:00,180
So, now that it's outside this function, this is no longer a local variable.
13

14
00:01:00,210 --> 00:01:02,240
It's now a global variable.
14

15
00:01:02,370 --> 00:01:09,120
And that means that unless we change the access level, any other class could access our instance of the
15

16
00:01:09,120 --> 00:01:11,050
calculator and mess with it.
16

17
00:01:11,130 --> 00:01:12,720
That's not what we want.
17

18
00:01:12,750 --> 00:01:18,540
So let's go ahead and add that private keyword which we add in front of all of our global variables
18

19
00:01:18,570 --> 00:01:19,740
by default.
19

20
00:01:19,740 --> 00:01:28,350
Now, the next problem is that Xcode tells us that you cannot use display value within a property initializer
20

21
00:01:28,740 --> 00:01:33,180
because the property initializers run before 'self' is available.
21

22
00:01:33,180 --> 00:01:35,190
Now, what does all of that mean?
22

23
00:01:35,190 --> 00:01:42,240
Well, it means that because this is a global variable, which happens even before viewDidLoad gets called,
23

24
00:01:43,080 --> 00:01:50,940
the Swift compiler can be sure that display value is not nil at the point when you're trying to initialize
24

25
00:01:50,970 --> 00:01:52,570
CalculatorLogic.
25

26
00:01:52,620 --> 00:02:00,540
So depending on how long it takes to initialize the screen to call viewDidLoad, to do all of the prep work,
26

27
00:02:00,540 --> 00:02:07,740
then displayValue may or may not be nil when you're calling this line of code to create a new
27

28
00:02:07,740 --> 00:02:09,550
CalculatorLogic struct.
28

29
00:02:09,750 --> 00:02:12,560
And this means that we can't use it here.
29

30
00:02:12,660 --> 00:02:21,000
So let's fix this. Now, instead of passing in displayValue to initialize our calculator,
30

31
00:02:21,330 --> 00:02:27,660
let's go ahead and delete that, and instead, make our property number an optional.
31

32
00:02:27,660 --> 00:02:33,640
So this means that we can pass in a value to this property at a later point.
32

33
00:02:33,900 --> 00:02:41,600
And when this struct CalculatorLogic gets initialized, this number property can be nil.
33

34
00:02:41,730 --> 00:02:43,210
And that kind of makes sense, right?
34

35
00:02:43,230 --> 00:02:50,370
When you create a brand-new CalculatorLogic, if the user hasn't pressed any of the buttons on the calculator
35

36
00:02:50,370 --> 00:02:54,070
yet, then it shouldn't really have a number, right?
36

37
00:02:54,150 --> 00:03:02,690
But if this number is a Double, then before we use it, we have to check to make sure that it's not nil.
37

38
00:03:02,940 --> 00:03:12,810
So if let n = number, then that means that number is not nil, and we can now use it inside our
38

39
00:03:12,810 --> 00:03:21,150
code by replacing the places where we use number with this unwrapped n which is a double, rather than
39

40
00:03:21,330 --> 00:03:22,750
an optional double.
40

41
00:03:23,130 --> 00:03:25,700
So, now let's get back to our ViewController.
41

42
00:03:25,920 --> 00:03:32,370
Now, at this point, if you have any lingering errors, be sure to hit command B to force your app to build
42

43
00:03:32,670 --> 00:03:36,940
so that any of the errors that are no longer meant to be here gets removed.
43

44
00:03:37,100 --> 00:03:43,890
Now, the next thing I want to change is inside our struct CalculatorLogic.Our number property
44

45
00:03:43,920 --> 00:03:47,020
at the moment is a global variable.
45

46
00:03:47,150 --> 00:03:50,250
And do you remember what we said about global variables?
46

47
00:03:50,250 --> 00:03:58,410
They should always have the private access level by default because, otherwise, this property is accessible
47

48
00:03:58,410 --> 00:04:01,370
from all other classes within our app.
48

49
00:04:01,560 --> 00:04:08,430
And that means that it could get altered or changed or turned to nil intentionally or unintentionally,
49

50
00:04:08,550 --> 00:04:16,070
which is not what we want, because this property number is integral to our CalculatorLogic model.
50

51
00:04:16,140 --> 00:04:18,180
It's nobody else's business.
51

52
00:04:18,330 --> 00:04:26,370
So instead, we can create a function that allows other classes to set the value of this number property.
52

53
00:04:26,940 --> 00:04:29,050
So we can say setNumber,
53

54
00:04:29,190 --> 00:04:32,580
and as an input, we want to be able to pass in a Double.
54

55
00:04:32,580 --> 00:04:41,820
Now, at this stage, I can name my function setNumber(number: Double) and then do this. But that doesn't
55

56
00:04:41,940 --> 00:04:43,940
really read very well, does it?
56

57
00:04:43,980 --> 00:04:50,940
When I call the function, it's going to be something like setNumber number, and it's because this parameter
57

58
00:04:50,940 --> 00:04:53,540
name is completely unnecessary.
58

59
00:04:53,550 --> 00:05:03,510
So as it stands, if I wanted to set the number over here, I would have to call calculator.setNumber, and
59

60
00:05:03,510 --> 00:05:05,350
then pass in the number
60

61
00:05:05,360 --> 00:05:08,110
that I want to pass which will be the displayValue
61

62
00:05:08,130 --> 00:05:15,060
in this case. Now that works, but I don't actually need this parameter name because the name of the method
62

63
00:05:15,150 --> 00:05:20,170
is already explicit enough as to what this method does.
63

64
00:05:20,190 --> 00:05:27,450
So I'd really like to be able to delete this part. Now, in order to be able to call that method like this,
64

65
00:05:27,450 --> 00:05:32,620
then over here, I can add an underbar, and then a space,
65

66
00:05:32,790 --> 00:05:39,030
and you might have seen the syntax across other Xcode projects, especially Apple's example projects. They
66

67
00:05:39,030 --> 00:05:40,210
love doing this.
67

68
00:05:40,570 --> 00:05:46,620
And what this means is that we're setting the external parameter name to be nothing,
68

69
00:05:47,100 --> 00:05:53,310
and we're setting the internal parameter name because you always need one inside to be able to use the
69

70
00:05:53,310 --> 00:05:57,410
thing that got passed in, right, to number.
70

71
00:05:57,880 --> 00:06:07,000
So if I changed this to, I don't know, num, and I have a setNumber, parentheses, num number, then that means
71

72
00:06:07,030 --> 00:06:12,320
my external parameter name is num and my internal name is number.
72

73
00:06:12,520 --> 00:06:19,090
So inside the curly braces, I will refer to the item that was passed into this function as number, and
73

74
00:06:19,240 --> 00:06:21,700
outside of the parameter name,
74

75
00:06:21,820 --> 00:06:24,580
then I would refer to it as num.
75

76
00:06:24,670 --> 00:06:27,500
But we wanted to not have a parameter name.
76

77
00:06:27,580 --> 00:06:33,820
So we're going to change the external one to an underscore. And instead of printing the number that got
77

78
00:06:33,820 --> 00:06:40,620
passed in, we want to set this private property to equal the value that was passed in.
78

79
00:06:40,630 --> 00:06:43,180
Now, in order to achieve that, I would write something like
79

80
00:06:43,180 --> 00:06:50,940
number = number which is really confusing, because which number is which?
80

81
00:06:50,950 --> 00:06:56,650
Which one of my setting? Am I trying to set this number or am I trying to set this number? And you can see,
81

82
00:06:56,650 --> 00:07:02,350
Swift actually gives you an error saying that number is a let constant because it thinks that you're trying
82

83
00:07:02,350 --> 00:07:04,230
to change this value.
83

84
00:07:04,330 --> 00:07:11,820
So what we do in this case? If we wanted to refer to this global property, we can simply say
84

85
00:07:11,830 --> 00:07:14,420
self.number is equal to number.
85

86
00:07:14,770 --> 00:07:22,090
And this means that anybody else who's looking at your code knows that I'm looking for a property inside
86

87
00:07:22,150 --> 00:07:28,090
the current class or the current struct namely inside the curly braces
87

88
00:07:28,150 --> 00:07:36,160
that's called number which is, of course, this one on line 13. And I'm setting it to equal the number that
88

89
00:07:36,220 --> 00:07:39,980
is the local variable which is this one.
89

90
00:07:40,010 --> 00:07:45,010
Now, the next problem we have is it tells us "Cannot assign to property:
90

91
00:07:45,010 --> 00:07:49,620
'self' is immutable. Mark method 'mutating' to make 'self' mutable."
91

92
00:07:49,660 --> 00:07:51,330
So you should be familiar with this already
92

93
00:07:51,340 --> 00:07:56,350
because we saw this when we were learning about struct, because we're creating this function
93

94
00:07:56,560 --> 00:07:58,920
inside our Swift structure.
94

95
00:07:59,230 --> 00:08:04,430
And this line of code modifies one of the properties of the struct.
95

96
00:08:04,450 --> 00:08:12,310
So if you remember, when you use a struct or when you pass around a struct, it does so by copying all
96

97
00:08:12,310 --> 00:08:13,550
of the values.
97

98
00:08:13,570 --> 00:08:21,460
So if this number had a value, say, it was 2, and this method inside the struct actually needs to change the
98

99
00:08:21,460 --> 00:08:31,150
value of this property to, say, 3, then this method has to be marked with mutating. Because this tells a
99

100
00:08:31,150 --> 00:08:37,560
Swift compiler that this method is capable of changing the properties inside the struct.
100

101
00:08:37,750 --> 00:08:42,130
And that means that it knows to make a brand-new copy of the struct
101

102
00:08:42,250 --> 00:08:49,030
when this function is run, so that it can update the property. Now, by doing that, we've created one more
102

103
00:08:49,030 --> 00:08:50,220
problem for ourselves.
103

104
00:08:50,260 --> 00:08:56,170
If you head back over to ViewController.swift, you can see that Xcode gives us an error saying that
104

105
00:08:56,170 --> 00:09:04,540
you cannot use a mutating member on an immutable value because calculator is a 'let' constant.
105

106
00:09:04,540 --> 00:09:05,490
What does that mean?
106

107
00:09:05,590 --> 00:09:12,850
Well, here,we're calling this function called setNumber which, remember, is a mutating function.
107

108
00:09:12,910 --> 00:09:20,500
It changes one of the properties of our struct. And in the last lesson, we spoke about what made structs
108

109
00:09:20,590 --> 00:09:22,050
different from classes,
109

110
00:09:22,240 --> 00:09:26,350
and one of those things was that they have true immutability.
110

111
00:09:26,350 --> 00:09:34,540
So that means that if you create a new structure that is declared as a "let" constant, then you can't change
111

112
00:09:34,810 --> 00:09:38,730
any of the properties inside that struct at a later point.
112

113
00:09:38,740 --> 00:09:44,980
So when we call this function and it changes our property, then this is why Xcode is getting angry at
113

114
00:09:44,980 --> 00:09:49,340
us, because you said that you weren't going to change this calculator ever,
114

115
00:09:49,360 --> 00:09:50,550
right?
115

116
00:09:50,560 --> 00:09:53,120
So Xcode could be really passive-aggressive like that.
116

117
00:09:53,200 --> 00:10:00,040
But let's go ahead and fix it to make it happy because, as we all know, a happy Xcode equals a happy
117

118
00:10:00,040 --> 00:10:01,230
app developer, right?
118

119
00:10:01,420 --> 00:10:04,360
So let's just quickly recap what we've done so far.
119

120
00:10:04,390 --> 00:10:11,800
We've created this global variable that is called calculator and it's a new instance of our struct 
120

121
00:10:11,800 --> 00:10:18,200
CalculatorLogic, and we've marked it as private to prevent other classes from messing with our calculator.
121

122
00:10:18,370 --> 00:10:26,350
Now, when one of the calculation buttons gets pressed, then we call the setNumber function which sets
122

123
00:10:26,620 --> 00:10:33,150
the number inside CalculatorLogic to whatever is currently inside the display.
123

124
00:10:33,160 --> 00:10:38,390
So let's say that on our calculator, the user taps on the number 5.
124

125
00:10:38,620 --> 00:10:45,360
At this point in our code, we set the display value to 5. Next, the user taps on the plus sign.
125

126
00:10:45,460 --> 00:10:52,810
And because this is one of the calculate buttons, then our IBAction calcButtonPressed will get called.
126

127
00:10:53,200 --> 00:11:01,230
And inside that IBAction, we call setNumber on our calculator structure and we set the number in the
127

128
00:11:01,230 --> 00:11:08,770
calculator to 5. And then we also call the calculate function passing in that plus sign as the symbol.
128

129
00:11:09,090 --> 00:11:11,910
Next, the user taps on 3.
129

130
00:11:12,300 --> 00:11:18,040
At this point, we set the display value to 3. And finally, they tap on the equal sign.
130

131
00:11:18,180 --> 00:11:25,050
So the calcButtonPressed IBAction gets called yet again, and we set our calculator's number property
131

132
00:11:25,110 --> 00:11:31,600
to 3, and we call the calculate function, again, passing in the symbol equals.
132

133
00:11:31,710 --> 00:11:40,290
So when they tap on the plus button, we need to save that data somewhere in our CalculatorLogic.
133

134
00:11:40,290 --> 00:11:46,470
We need to save the first number that they wanted to calculate and the calculation that they wanted
134

135
00:11:46,470 --> 00:11:48,670
to make which is to add.
135

136
00:11:48,840 --> 00:11:53,860
Now, I could say that all in separate properties, right, up here,
136

137
00:11:54,000 --> 00:12:01,490
or I could create a brand-new struct that contains the first number and the operation they want to make.
137

138
00:12:01,620 --> 00:12:03,130
But that seems a bit overkill.
138

139
00:12:03,150 --> 00:12:07,630
Now, what's in between creating a new struct and creating a simple property?
139

140
00:12:07,740 --> 00:12:14,100
Well, in Swift, we have something called tuples, and that is what we're going to learn about in the next
140

141
00:12:14,100 --> 00:12:14,730
episode.
141

142
00:12:14,820 --> 00:12:17,340
So for all of that and more, I'll see you there.
