0
1
00:00:01,350 --> 00:00:07,070
In this lesson, we'll get the grips with UISliders and get them working inside our app.
1

2
00:00:07,260 --> 00:00:14,140
So you should have cloned the starting project and have the project open inside Xcode.
2

3
00:00:14,250 --> 00:00:18,060
Now, first, let's take a look around the starting project.
3

4
00:00:18,060 --> 00:00:25,470
So notice that we've got our Models, View, and Controller folders already created for you. And in our Views
4

5
00:00:25,470 --> 00:00:25,890
folder,
5

6
00:00:25,890 --> 00:00:32,280
we've got our Main.storyboard that has all our designs. But in this case, we've actually got two screens
6

7
00:00:32,340 --> 00:00:37,920
or two view controllers, compared to previously where we've limited ourselves to building single-screen
7

8
00:00:37,920 --> 00:00:39,630
applications.
8

9
00:00:39,630 --> 00:00:44,580
So in this case, we're going to have one screen which is for the calculator where the user toggles their
9

10
00:00:44,580 --> 00:00:49,470
height and weight, and then presses the calculate button. And then, that will take them to the next screen
10

11
00:00:49,740 --> 00:00:52,970
where it shows them their result and some advice.
11

12
00:00:53,100 --> 00:00:57,830
Now, notice that in the calculator view, we've added some UISliders.
12

13
00:00:57,900 --> 00:01:02,850
And if you need to find them they're in exactly the same place that you won't find everything which
13

14
00:01:02,850 --> 00:01:04,980
is, of course, in our object's library.
14

15
00:01:04,980 --> 00:01:11,930
And here we've got a Slider. So it displays a horizontal bar and it represents a range of values.
15

16
00:01:12,150 --> 00:01:16,810
We can define the maximum and the minimum values in the Attribute Inspector
16

17
00:01:16,830 --> 00:01:19,170
once we have the Slider selected.
17

18
00:01:19,170 --> 00:01:26,820
So for my height, which is in meters, I've got the minimum to be 0 meters which, hopefully, nobody is.
18

19
00:01:27,110 --> 00:01:33,190
And I've got the maximum at 3 meters. now, the weight I've set to be zero and 200.
19

20
00:01:33,210 --> 00:01:36,480
So you can feel free to adjust these as you see fit.
20

21
00:01:36,480 --> 00:01:39,420
But I think these will work fine for most people.
21

22
00:01:39,420 --> 00:01:47,670
Notice how we've got these labels here inside a Stack View, and these labels should update to equal the
22

23
00:01:47,670 --> 00:01:51,030
value of the thumb in the Slider track.
23

24
00:01:51,030 --> 00:01:55,030
So I've set the starting value to be 1.5.
24

25
00:01:55,050 --> 00:02:01,170
Now, you can also set it to be at the beginning if you wanted it to be at zero which is the minimum value,
25

26
00:02:01,560 --> 00:02:05,970
but I quite like starting it out in the middle it, looks quite neat.
26

27
00:02:05,970 --> 00:02:11,080
Notice there's also a warning up here that says, "View Controller" is unreachable.
27

28
00:02:11,220 --> 00:02:16,020
And when we click on it, it tells us which one it's referring to which is, of course, this Result View
28

29
00:02:16,020 --> 00:02:16,950
Controller.
29

30
00:02:16,950 --> 00:02:21,810
But don't worry about this warning for now, we're going to fix it when we learn about multi-screen apps
30

31
00:02:22,140 --> 00:02:24,980
and how to navigate to this second screen.
31

32
00:02:25,020 --> 00:02:27,560
For now, we can just safely ignore it.
32

33
00:02:27,990 --> 00:02:32,580
But what we can't ignore right now is our Sliders don't yet work.
33

34
00:02:33,300 --> 00:02:36,210
Now, the behavior that we're after is something like this.
34

35
00:02:36,240 --> 00:02:44,320
We should be able to move the slider along the track and see the Height label here on the right updates.
35

36
00:02:44,910 --> 00:02:52,320
So every time I move the slider, then the associated labels should change its values according to where
36

37
00:02:52,320 --> 00:02:58,410
I am on the slider from the minimum of 10 to the maximum of 200, and the height goes from zero all the
37

38
00:02:58,410 --> 00:03:00,150
way up to three.
38

39
00:03:00,210 --> 00:03:05,760
Now, the height has two decimal places of accuracy, whereas the weight is rounded to the nearest whole
39

40
00:03:05,760 --> 00:03:06,210
number.
40

41
00:03:06,570 --> 00:03:08,080
So that's the objective.
41

42
00:03:08,100 --> 00:03:11,090
That's the behavior we're aiming for by the end of this lesson.
42

43
00:03:11,430 --> 00:03:14,380
But let's break it down into a series of steps.
43

44
00:03:14,430 --> 00:03:17,510
The first step will be printing the value of the slider
44

45
00:03:17,650 --> 00:03:19,860
when we move it along the track.
45

46
00:03:19,860 --> 00:03:21,240
So here's a challenge for you.
46

47
00:03:21,270 --> 00:03:27,990
Can you link up the height slider with an IBAction called height slider changed, and the weight slider
47

48
00:03:28,020 --> 00:03:33,960
with an IBAction called weight slider changed, and then figure out how you can print out the value
48

49
00:03:33,960 --> 00:03:34,940
of each slider
49

50
00:03:35,070 --> 00:03:39,960
when they do in fact get changed. I'll give you a few seconds the pause the video before I show you the
50

51
00:03:39,960 --> 00:03:43,620
solution.
51

52
00:03:43,770 --> 00:03:44,190
All right.
52

53
00:03:44,220 --> 00:03:45,950
So how did you do?
53

54
00:03:46,000 --> 00:03:47,470
Did you give that a go?
54

55
00:03:47,470 --> 00:03:52,600
Well, the first thing that we need to do is, of course, link up some IBActions, right?
55

56
00:03:52,600 --> 00:03:57,280
This is a component that can take user interactions just like the button.
56

57
00:03:57,340 --> 00:03:58,240
How do we do that?
57

58
00:03:58,270 --> 00:04:05,750
We, of course, pull up our assistant view, and then we can start linking up our design with our code.
58

59
00:04:05,920 --> 00:04:12,370
And I'm going to select this horizontal slider which you can see is the height slider and I'm going
59

60
00:04:12,370 --> 00:04:20,920
to control, drag over here, and I'm going to call that action the heightSliderChanged.
60

61
00:04:20,920 --> 00:04:30,430
And notice how the event type that triggers this IBAction is when the value of my slider changes.
61

62
00:04:30,490 --> 00:04:35,830
And to be more accurate and to make life easier for me down the line, I'm going to change the data type to
62

63
00:04:35,830 --> 00:04:39,160
be a more precise data type, rather than any data type.
63

64
00:04:39,340 --> 00:04:44,320
It's going to be a UISlider that's going to be linked to this action.
64

65
00:04:44,410 --> 00:04:50,170
So that's my height slider done and now I'm going to do the same with my weight slider.
65

66
00:04:50,200 --> 00:04:58,990
So this one's going to be called weightSliderChanged. And, again, change the type to UISlider, hit Connect.
66

67
00:04:58,990 --> 00:05:07,150
So now I've got my two IBActions down. Now, the next step is how do I change my code so that whenever
67

68
00:05:07,210 --> 00:05:16,000
this IBAction gets triggered, I can print out the value of my slider where I am on this slider track?
68

69
00:05:17,680 --> 00:05:24,820
So we know that when we select these UISliders in the interface builder, and when we look in the Attribute
69

70
00:05:24,820 --> 00:05:30,310
Inspector, the value property is the one that we actually want,
70

71
00:05:30,310 --> 00:05:30,610
right?
71

72
00:05:30,610 --> 00:05:32,850
Like right now, it's set to 1.5,
72

73
00:05:32,980 --> 00:05:39,850
but I could set it to 1.7, or I could set it to zero, and that moves the little circle along
73

74
00:05:39,850 --> 00:05:40,930
the track.
74

75
00:05:40,930 --> 00:05:48,730
Now, if we go and check in our IBAction, notice how we've got a sender which has a data type of
75

76
00:05:48,730 --> 00:05:49,510
UISlider.
76

77
00:05:50,890 --> 00:05:58,240
So if we tap into the sender which is, of course, that slider, and we wlrite a dot, you can also just scroll
77

78
00:05:58,240 --> 00:06:03,490
through this list and see if there's any properties that you think might be what you want.
78

79
00:06:03,730 --> 00:06:08,770
And we can see that there's actually a property that matches the one we saw in the Attribute Inspector.
79

80
00:06:09,190 --> 00:06:14,520
The value and the explanation is that this will be equal to the slider's current value.
80

81
00:06:14,530 --> 00:06:17,830
Well, that sounds pretty much like exactly what we need.
81

82
00:06:18,010 --> 00:06:24,160
So now all we need is to wrap it inside a print statement, and then copy it over to the weightSlider
82

83
00:06:24,160 --> 00:06:30,610
as well. And you've now got the functionality that we described,
83

84
00:06:30,850 --> 00:06:36,280
so that completes the first two steps. We've linked our Sliders to our View Controller and we've successfully
84

85
00:06:36,280 --> 00:06:39,540
access the value of each Slider.
85

86
00:06:39,610 --> 00:06:45,520
The next thing to notice is that when these values get printed, well, they actually have quite a lot of
86

87
00:06:45,520 --> 00:06:47,100
decimal places.
87

88
00:06:47,140 --> 00:06:53,090
That's a high level of precision. But we don't really need it to be so precise.
88

89
00:06:53,110 --> 00:06:54,490
Here's another challenge for you.
89

90
00:06:54,610 --> 00:07:03,170
Can you figure out how to round the height slider value down to only two decimal places?
90

91
00:07:03,340 --> 00:07:11,010
So we move the high slider, the goal is to only have two decimal places being printed, rather than four
91

92
00:07:11,010 --> 00:07:11,630
or five.
92

93
00:07:12,490 --> 00:07:15,670
So pause the video and see if you can complete this challenge.
93

94
00:07:18,330 --> 00:07:20,210
So there's quite a few ways of doing this.
94

95
00:07:20,220 --> 00:07:28,200
But if I did a just cursory search of how to round a number to two decimal places using Swift, then one
95

96
00:07:28,200 --> 00:07:33,650
of the solutions that you might come across is to use the String formatting.
96

97
00:07:33,840 --> 00:07:39,660
So we pass in the number that we want to be rounded and then we specify the number of decimal places
97

98
00:07:39,660 --> 00:07:47,260
we want by using this "%." and the 2f refers to two decimal places after the floating point,
98

99
00:07:47,460 --> 00:07:52,900
or you could have one 1f for one decimal place, 0f for zero decimal places.
99

100
00:07:52,920 --> 00:08:00,720
So let's try this. In our heightSlider, we already know that we can get access to the sender.value
100

101
00:08:01,320 --> 00:08:05,240
which is going to be quite precise, so it has a lot of decimal places.
101

102
00:08:05,430 --> 00:08:11,040
And this is going to be the thing that we want to round. And if we apply the code that we found here
102

103
00:08:11,070 --> 00:08:15,840
where we write String, and then we type format just like we saw.
103

104
00:08:15,850 --> 00:08:25,320
Well, this particular method is going to return a String initialized by using a given format string as
104

105
00:08:25,350 --> 00:08:30,440
a template into which the remaining argument values are substituted.
105

106
00:08:30,450 --> 00:08:34,980
That sounds pretty confusing but, essentially, all it takes are two inputs:
106

107
00:08:34,980 --> 00:08:38,630
the format string and the thing that you want to format.
107

108
00:08:38,970 --> 00:08:44,770
In this case, the thing that we want to format is, of course, sender.value, so we'll put that in here.
108

109
00:08:45,060 --> 00:08:54,120
And the format string as we saw before, we just had to put "%.2f" just as we have in the
109

110
00:08:54,120 --> 00:09:02,180
code snippet here. And then finally, we're going to go ahead and print this entire string.
110

111
00:09:02,300 --> 00:09:09,320
And now if we run our app, you'll see that functionality I described earlier on,
111

112
00:09:09,350 --> 00:09:12,350
so two decimal places.
112

113
00:09:12,350 --> 00:09:15,200
The next thing to do is our weight slider.
113

114
00:09:15,320 --> 00:09:18,180
We want it to be a whole number.
114

115
00:09:18,320 --> 00:09:23,320
So when we move the weight slider, we don't want to see any decimal places.
115

116
00:09:23,390 --> 00:09:25,960
And so I'm, again, going to leave this as a challenge to you.
116

117
00:09:25,970 --> 00:09:28,810
There's actually multiple ways of doing the same thing.
117

118
00:09:28,940 --> 00:09:35,190
But pause the video and see if you can achieve this effect.
118

119
00:09:35,510 --> 00:09:35,820
All right.
119

120
00:09:35,850 --> 00:09:41,940
So in this case, we could have done what we did before which is where we simply do string format the
120

121
00:09:42,000 --> 00:09:47,980
sender.value, and instead of two decimal places or "2f," we put "0f."
121

122
00:09:48,240 --> 00:09:53,410
And now when we run our app, you can see that we have no decimal places.
122

123
00:09:53,490 --> 00:10:00,480
Now, the alternative way of doing this is we could have also converted our sender.value, which if
123

124
00:10:00,480 --> 00:10:07,110
you check is actually a floating point number, we could actually just convert it into an integer by writing
124

125
00:10:07,130 --> 00:10:12,640
"int," and then having a set of parenthese,s and inside we write sender.value.
125

126
00:10:12,640 --> 00:10:20,600
Now, when I do that, you'll see that I get the same effect again with numbers with no decimal places.
126

127
00:10:20,620 --> 00:10:27,010
So now that we've got our height to two decimal places, I'll wait to no decimal places.
127

128
00:10:27,100 --> 00:10:35,260
We're ready to move on and get the user to be able to see these values. Firstly, we're going to add some
128

129
00:10:35,320 --> 00:10:41,140
IBOutlets. The place that we want to display these values are, of course, this label and this label
129

130
00:10:41,140 --> 00:10:46,540
right here, because the user can't see the debug area, so we need to be able to put these values onto
130

131
00:10:46,540 --> 00:10:49,220
the screen. At the top of my file,
131

132
00:10:49,240 --> 00:10:58,000
I'm going to go ahead and control drag my hype label here and I'm just gonna call it heightLabel and, also,
132

133
00:10:58,030 --> 00:11:04,410
I'm going to create a link from this label right here which I'm going to call
133

134
00:11:04,420 --> 00:11:05,830
weightLabel.
134

135
00:11:05,830 --> 00:11:09,520
Now, I've got my two labels connected.
135

136
00:11:09,520 --> 00:11:11,350
Let's quickly format our code.
136

137
00:11:11,800 --> 00:11:16,310
Well how do I get these numbers into these labels?
137

138
00:11:16,750 --> 00:11:22,120
And I'd like to pose this as a challenge to you. Upon successfully completing the challenge,
138

139
00:11:22,150 --> 00:11:29,530
you should be able to move the slider and see these labels move with you from the maximum to the minimum
139

140
00:11:29,800 --> 00:11:31,780
reflecting the value of the slider.
140

141
00:11:32,260 --> 00:11:34,990
Pause the video and see if you can figure out how to do this
141

142
00:11:38,900 --> 00:11:46,190
Previously, we were already able to print these values to the desired accuracy into the debug console.
142

143
00:11:46,190 --> 00:11:52,340
We now need to get them into these heightLabels and weightLabels. So let's delete the print statement
143

144
00:11:52,610 --> 00:11:56,540
and we're left with the value that we want to put into the heightLabel.
144

145
00:11:56,540 --> 00:12:02,830
So now all we need to do is tap into our heightLabel and then get hold of its
145

146
00:12:02,870 --> 00:12:09,950
text property, and set it equal to the string that we formatted based on the sender.value.
146

147
00:12:09,950 --> 00:12:16,550
Now, if you used this method that I showed earlier where we converted the sender.value into an integer,
147

148
00:12:16,550 --> 00:12:22,290
well it might be a little bit harder to put it into the weightLabel because when we write weightLabel.text
148

149
00:12:22,430 --> 00:12:25,610
equal to Int(sender.value)
149

150
00:12:26,000 --> 00:12:31,910
well, there's gonna be a type mismatch because the right-hand slide is an integer data type, whereas this
150

151
00:12:31,910 --> 00:12:34,920
text property needs a string data type.
151

152
00:12:35,000 --> 00:12:36,380
So how can we fix this?
152

153
00:12:36,380 --> 00:12:44,930
Well, one way is to wrap the integer inside a string. So we first convert this into a whole number and
153

154
00:12:44,930 --> 00:12:46,880
then we convert it into a string.
154

155
00:12:46,880 --> 00:12:52,700
But to be honest, that's quite roundabout, so we might as well just use the same method that we have above
155

156
00:12:53,060 --> 00:12:59,990
which is where we use the format, and then we have "%.0f" for zero decimal places, and then we
156

157
00:12:59,990 --> 00:13:02,720
put in our sender.value.
157

158
00:13:02,720 --> 00:13:11,750
So now if we run our app, you'll see that these labels move when I move the slider. But notice how previously,
158

159
00:13:11,780 --> 00:13:14,900
we had some units in there. But now we move them,
159

160
00:13:14,900 --> 00:13:16,480
the units are gone.
160

161
00:13:16,580 --> 00:13:23,300
Pause the video and see if you can change the code so that when we move the slider, the units stay as
161

162
00:13:23,300 --> 00:13:23,750
they are.
162

163
00:13:23,750 --> 00:13:28,270
So meters for the height and kilograms for the weight.
163

164
00:13:28,280 --> 00:13:30,950
So pause the video and try to do this.
164

165
00:13:33,530 --> 00:13:33,880
All right.
165

166
00:13:33,890 --> 00:13:37,810
So before we start formatting, this line is already getting pretty long.
166

167
00:13:37,820 --> 00:13:42,620
So let's go ahead and set this equal to a separate constant.
167

168
00:13:43,010 --> 00:13:50,600
So I'm going to write "let height" equal this, and then in my heightLabel, I'm gonna set the text property
168

169
00:13:50,630 --> 00:13:53,510
to be equal to an interpolated string.
169

170
00:13:53,660 --> 00:14:01,700
So I'm going to insert the value of my height in here, and then I'm going to tag on the meters unit, and
170

171
00:14:01,760 --> 00:14:05,930
I'm going to do the same with my weight, "let weight" equal that.
171

172
00:14:06,050 --> 00:14:17,660
And then my weightLabel.text is gonna be equal to the weight inserted into my string and then with
172

173
00:14:17,660 --> 00:14:20,720
my kilograms added on at the end.
173

174
00:14:20,750 --> 00:14:28,510
Now, we have this behavior that we want. In the next lesson, we'll use our slider values to calculate the
174

175
00:14:28,510 --> 00:14:35,710
BMI. But to do that, we need to be able to get hold of the slider values outside IBActions. For all
175

176
00:14:35,710 --> 00:14:38,050
of that and more, I'll see you on the next lesson.
