0
1
00:00:00,540 --> 00:00:01,080
Hey, guys.
1

2
00:00:01,110 --> 00:00:03,050
Welcome to the Swift
2

3
00:00:03,060 --> 00:00:06,720
Deep Dive on protocols. In this deep dive,
3

4
00:00:06,750 --> 00:00:11,910
Wwe're going to be talking about what Swift protocols are and what they allow us to do.
4

5
00:00:12,060 --> 00:00:19,770
So the way I like to think about protocols is imagine it as a certification that you have in your CV
5

6
00:00:19,800 --> 00:00:20,670
or your resume.
6

7
00:00:21,720 --> 00:00:28,020
So for example, in my LinkedIn profile, I've got a bunch of certificates that I've listed. And one of those
7

8
00:00:28,020 --> 00:00:30,860
certificates is something called Advanced Life Support.
8

9
00:00:31,320 --> 00:00:37,950
So this is something that every doctor in the UK has to complete and it's a two-day course where we
9

10
00:00:37,950 --> 00:00:44,220
learn a whole bunch of things, including how to deliver CPR to resuscitate people who might have had
10

11
00:00:44,280 --> 00:00:46,490
a cardiac arrest.
11

12
00:00:46,530 --> 00:00:54,150
Similarly in Swift, we can create these protocols or certifications if you will that have a bunch of
12

13
00:00:54,150 --> 00:01:02,100
requirements. And when our classes or our structs adopt this protocol, it means that they are able to
13

14
00:01:02,160 --> 00:01:08,690
meet these requirements and have these skills. For example, performing CPR or resuscitating somebody who's
14

15
00:01:08,700 --> 00:01:11,010
unconscious.
15

16
00:01:11,250 --> 00:01:16,290
So the way that we define our protocol starts with the protocol keyword.
16

17
00:01:16,290 --> 00:01:20,220
And then we give it a name. And similar to structure and classes,
17

18
00:01:20,220 --> 00:01:26,730
it's also named starting with a capital letter. And then in between a set of curly braces, we can define
18

19
00:01:26,850 --> 00:01:29,260
the requirements of this protocol.
19

20
00:01:29,340 --> 00:01:32,020
So let's take a look at this in more detail.
20

21
00:01:32,160 --> 00:01:39,240
I'm gonna head over to Xcode and create a new project and I'm gonna select the macOS command line
21

22
00:01:39,240 --> 00:01:43,380
tool to be able to allow us to see multiple files.
22

23
00:01:43,380 --> 00:01:51,240
I'm gonna call this product name Protocols Demo and then go ahead and hit next. And then you can save
23

24
00:01:51,240 --> 00:01:53,690
it wherever you want.
24

25
00:01:53,700 --> 00:01:59,310
Now, inside my Main.swift, I'm actually going to delete everything that's in there because we don't need
25

26
00:01:59,400 --> 00:02:05,880
any of it to write the code. Protocols is a fundamental aspect of Swift and it doesn't rely upon anything
26

27
00:02:05,880 --> 00:02:06,200
else.
27

28
00:02:07,330 --> 00:02:11,590
Now, let's write some code to see what problems protocols can solve.
28

29
00:02:11,590 --> 00:02:18,280
The first thing I'm gonna do is I'm going to create a new class and my class is going to be a Bird class
29

30
00:02:18,430 --> 00:02:22,070
and I'm going to define a bunch of things that birds can do.
30

31
00:02:22,090 --> 00:02:25,230
So for example, birds can usually fly.
31

32
00:02:25,840 --> 00:02:28,420
And so I've got a fly method in my Bird class.
32

33
00:02:28,990 --> 00:02:35,410
And when my bird flies, all that it does is it flaps its wings and it lifts off into the sky.
33

34
00:02:35,560 --> 00:02:42,010
So I'm going to create a very simple print statement to represent this functionality of a bird.
34

35
00:02:42,010 --> 00:02:48,040
Now, in addition, if a bird is female, then they can also lay eggs, right?
35

36
00:02:48,160 --> 00:02:57,910
So let's create this layEgg functionality where we check to make sure. If our bird is female, then in
36

37
00:02:57,910 --> 00:03:04,890
that case, we can go ahead and print "The bird makes a new bird in a shell."
37

38
00:03:04,900 --> 00:03:12,970
So here we've got our Bird class created. And based on what we learned in our classes Deep Dive, we know
38

39
00:03:12,970 --> 00:03:16,570
that we can inherit from different classes.
39

40
00:03:16,570 --> 00:03:24,640
So if I created another class, let's say, I create a Eagle class and it's going to be inheriting from
40

41
00:03:24,670 --> 00:03:26,210
the Bird class.
41

42
00:03:26,230 --> 00:03:34,090
So now I've got this Eagle subclass which inherits from my Bird class. The Eagle now gets access to everything
42

43
00:03:34,180 --> 00:03:35,060
a bird can do.
43

44
00:03:35,140 --> 00:03:42,490
So, for example, let's create our own Eagle. Let's call it myEagle and it's going to be a new Eagle object
44

45
00:03:42,550 --> 00:03:45,200
created from the Eagle class blueprint.
45

46
00:03:45,520 --> 00:03:54,690
And then I could say, well, myEagle, you can fly, myEagle if it's female, it can lay eggs, and we've set
46

47
00:03:54,700 --> 00:04:01,370
everything by default as female. So our eagle is able to fly and lay eggs. Pretty simple so far.
47

48
00:04:01,450 --> 00:04:08,050
Now, in our Eagle class, let's say that our Eagles are able to do something a little bit more specialized
48

49
00:04:08,320 --> 00:04:10,620
that maybe not all birds can do.
49

50
00:04:10,630 --> 00:04:20,260
Maybe it can also soar. So our Eagle is able to take advantage of the air currents. And using the warm air,
50

51
00:04:20,290 --> 00:04:27,610
it's able to glide through the air using these air currents and not all birds are able to lock their
51

52
00:04:27,610 --> 00:04:29,390
wings and do this apparently.
52

53
00:04:29,650 --> 00:04:36,530
Now, our Eagle is also in addition to everything it got from the bird class that it inherited,
53

54
00:04:36,880 --> 00:04:39,560
it's also able to soar.
54

55
00:04:39,610 --> 00:04:48,460
So now we've created are Bird class, we're able to inherit from our Bird class, and that's all just a
55

56
00:04:48,460 --> 00:04:55,050
review so far. At this point, you might be wondering, "Well, where's the problem here?"
56

57
00:04:55,060 --> 00:04:57,430
This is a really good time to use inheritance,
57

58
00:04:57,490 --> 00:04:58,370
right?
58

59
00:04:58,420 --> 00:05:04,870
Well, let's say that a couple months down the line, we create another class, myPenguin class which is
59

60
00:05:04,870 --> 00:05:07,260
also going to inherit from the Bird class.
60

61
00:05:07,270 --> 00:05:09,070
Penguins are indeed birds.
61

62
00:05:09,070 --> 00:05:15,790
They have wings and they have feathers. And penguins, in addition, can also swim.
62

63
00:05:15,790 --> 00:05:20,380
So my penguin is able to paddle through the water.
63

64
00:05:20,380 --> 00:05:25,260
So let's say that we create an object from our Penguin class. We'll call it myPenguin.
64

65
00:05:25,960 --> 00:05:30,040
And this is, of course, created from the Penguin class and we initialize it
65

66
00:05:33,720 --> 00:05:37,980
And now my penguin is able to lay eggs.
66

67
00:05:38,100 --> 00:05:51,390
It's able to swim. But curiously, it's also able to fly. It inherited that method because it's a bird.
67

68
00:05:51,390 --> 00:05:55,890
But as you may already know, penguins can't actually fly.
68

69
00:05:55,890 --> 00:06:03,960
Their wings are far too small to be able to support themselves in air. Now, we have a bit of a problem,
69

70
00:06:04,050 --> 00:06:04,790
right?
70

71
00:06:04,800 --> 00:06:12,270
We want to be able to define the penguin as a subtype of birds, but we don't really want it to inherit
71

72
00:06:12,300 --> 00:06:14,170
the fly method.
72

73
00:06:14,220 --> 00:06:19,950
So this is the first problem we run into our Penguin is inheriting some functionality that it shouldn't
73

74
00:06:19,950 --> 00:06:20,660
have,
74

75
00:06:20,910 --> 00:06:31,250
And this can lead to unintended consequences like a flying Penguin. Let's say that we had a flying museum,
75

76
00:06:31,280 --> 00:06:37,220
right? Let's call it FlyingMuseum and let's create as a structure because we don't need to inherit anything,
76

77
00:06:37,310 --> 00:06:40,040
we don't need any of the class features.
77

78
00:06:40,220 --> 00:06:48,230
So let's say that we have our flying museum which puts on these flying demos every so often. And in these
78

79
00:06:48,230 --> 00:06:51,610
demos, it takes a flying object.
79

80
00:06:51,620 --> 00:06:55,360
So it has to be able to fly to be able to do this demo.
80

81
00:06:55,400 --> 00:07:03,140
So the flying object, we're going to say it's of type bird, because we know that all birds can fly.
81

82
00:07:03,170 --> 00:07:07,190
They have this function fly in their class definition.
82

83
00:07:07,970 --> 00:07:15,290
So now when our flyingMuseum puts on the flyingDemo, well, all it does is it collects all of these things
83

84
00:07:15,290 --> 00:07:16,400
that can fly,
84

85
00:07:17,210 --> 00:07:19,730
and it gets the flying object to fly.
85

86
00:07:20,750 --> 00:07:31,640
So now let's create our museum, which is a flying museum, and our museum puts on a show, a flyingDemo.
86

87
00:07:31,730 --> 00:07:39,530
So let's huddle up all of our birds that we have access to in our museum and let's get myEagle to be passed
87

88
00:07:39,530 --> 00:07:42,990
in as the input to the flyingDemo.
88

89
00:07:44,450 --> 00:07:53,870
So now if I run this code as it is, you can see that once it's done running, I get the bird flaps its
89

90
00:07:53,870 --> 00:07:55,910
wings and lifts off into the sky.
90

91
00:07:56,330 --> 00:08:02,990
So the only reason why I'm able to do this is because I was able to pass myEagle, which is an eagle
91

92
00:08:02,990 --> 00:08:13,040
type, into the flyingDemo as a flyingObject because the Eagle class inherits from the bird Class, and
92

93
00:08:13,040 --> 00:08:20,180
therefore, it's also a bird type which, therefore, satisfies the data type of this input.
93

94
00:08:20,180 --> 00:08:23,900
So it's able to be used in my flyingDemo.
94

95
00:08:23,900 --> 00:08:30,350
Now, similarly, if I create my penguin and I pass in myPenguin,
95

96
00:08:30,890 --> 00:08:36,500
and when I run my code, we get a flying penguin and a very surprised audience at the museum's flying
96

97
00:08:36,500 --> 00:08:37,450
demo.
97

98
00:08:37,460 --> 00:08:43,460
This is the kind of unintended behavior I was talking about. The entire code base assumes that all birds
98

99
00:08:43,460 --> 00:08:48,770
can fly, but we have one bird that clearly shouldn't be flying.
99

100
00:08:48,830 --> 00:08:55,940
So the problem is that we're relying too heavily on inheritance and subclassing. Say, your app has become
100

101
00:08:55,970 --> 00:09:01,440
a huge hit and now you want to have flying behavior in other parts of your code,
101

102
00:09:01,490 --> 00:09:06,060
well, birds shouldn't be the only thing your museum is showing off in the flying demo, right?
102

103
00:09:06,500 --> 00:09:09,380
So how would you get that to work?
103

104
00:09:09,380 --> 00:09:15,670
Let's say that I had a structure that's an airplane. And my airplane,
104

105
00:09:15,670 --> 00:09:19,600
well, I also want to say that, well, airplanes can fly, right?
105

106
00:09:19,610 --> 00:09:24,560
So at the moment, the only things that can fly are birds.
106

107
00:09:24,590 --> 00:09:27,750
That's the one that has the fly method implemented.
107

108
00:09:27,750 --> 00:09:35,330
And if I want to be able to use my airplane in my flying demo, well, then it kind of has to be a bird
108

109
00:09:35,390 --> 00:09:39,720
type because that's the only thing that I can put in here.
109

110
00:09:39,890 --> 00:09:49,130
If I just had an airplane struct that I created down here, let myPlane equals Airplane, and I tried to
110

111
00:09:49,160 --> 00:09:53,360
pass in myPlane in here as the input,
111

112
00:09:53,360 --> 00:10:01,280
well, then I'm going to get an error because this has a type of airplane which is not in any way related
112

113
00:10:01,520 --> 00:10:08,890
to type bird which is what I'm making a requirement as the input type.
113

114
00:10:08,930 --> 00:10:10,010
So what can we do?
114

115
00:10:10,010 --> 00:10:18,560
Well, we could force our code to work by making our airplane a type of bird. But now we have a problem
115

116
00:10:18,590 --> 00:10:20,690
because structures cannot inherit.
116

117
00:10:21,170 --> 00:10:28,250
So let's go ahead and fudge our code a little bit more and turn our airplane into a class to make it
117

118
00:10:28,250 --> 00:10:30,000
inherit from bird.
118

119
00:10:30,080 --> 00:10:37,100
So now that works, but let's see what happens when we put our plane into the flyingDemo.
119

120
00:10:37,100 --> 00:10:41,220
It says that the bird flaps its wings and lifts off into the sky.
120

121
00:10:41,240 --> 00:10:42,950
But, actually, wait a minute.
121

122
00:10:42,950 --> 00:10:44,270
It's a--it's an airplane.
122

123
00:10:44,300 --> 00:10:46,070
What's going on here?
123

124
00:10:46,070 --> 00:10:54,920
Well, it's because the plane inherits from bird which has the implementation of fly and fly says that
124

125
00:10:55,070 --> 00:10:59,750
the bird flaps its wings and lifts off into the sky which is fair enough for birds.
125

126
00:10:59,750 --> 00:11:04,100
But it's very weird for an airplane to flap its wings.
126

127
00:11:04,100 --> 00:11:13,340
So while we could, let's say, override our methods fly. And, you know, for airplanes we could print, instead,
127

128
00:11:13,370 --> 00:11:17,960
that the airplane uses its engine to lift off into the air.
128

129
00:11:17,960 --> 00:11:25,660
And now, I've kind of forced my code to work because this is now what we're getting in our flyingDemo.
129

130
00:11:26,300 --> 00:11:29,720
But there are headaches with this way of doing things.
130

131
00:11:29,780 --> 00:11:38,700
For example, my plane is now able to lay eggs which makes absolutely zero sense, whatsoever.
131

132
00:11:38,780 --> 00:11:41,570
So how can we solve this problem?
132

133
00:11:41,690 --> 00:11:45,170
How can we separate the flying behavior from the bird class?
133

134
00:11:45,170 --> 00:11:48,950
How can we have both classes and structures that can fly?
134

135
00:11:49,670 --> 00:11:53,030
Remember that inheritance only works for classes.
135

136
00:11:53,450 --> 00:11:58,950
So maybe we shouldn't be using inheritance to get hold of the flying functionality at all.
136

137
00:11:59,120 --> 00:12:02,280
And this is where protocols come to the rescue.
137

138
00:12:02,300 --> 00:12:07,610
So let me just clear up my code a little bit to make it easier to see what's going on.
138

139
00:12:07,610 --> 00:12:14,180
And right at the top, I'm going to declare a protocol. The name of my protocol is going to be called
139

140
00:12:14,180 --> 00:12:14,720
CanFly.
140

141
00:12:15,410 --> 00:12:19,150
And this is, basically, like the certificate that I mentioned before.
141

142
00:12:19,280 --> 00:12:21,070
So everybody that can fly,
142

143
00:12:21,070 --> 00:12:22,840
they've gone to the flying training.
143

144
00:12:22,940 --> 00:12:29,660
They have this capability of flying. But in order for you to be someone that can fly or something that
144

145
00:12:29,660 --> 00:12:30,680
can fly,
145

146
00:12:30,680 --> 00:12:32,290
well, we have some requirements.
146

147
00:12:32,360 --> 00:12:36,800
You must be able to implement a fly method.
147

148
00:12:36,800 --> 00:12:43,400
Now, notice how this fly method that goes into the protocol doesn't actually have an implementation.
148

149
00:12:43,400 --> 00:12:47,450
It doesn't have a set of curly braces which defines how it should be flying.
149

150
00:12:47,480 --> 00:12:52,730
And in fact, if you try to do this, Xcode will give you a warning saying, "Protocol methods must not have
150

151
00:12:52,820 --> 00:12:53,660
bodies."
151

152
00:12:53,660 --> 00:13:04,070
So it only has this part. It can't have any curly braces and any implementation. Now, that we've created
152

153
00:13:04,070 --> 00:13:11,000
this can fly certificate with a fly method that must be implemented by everyone who says that they can
153

154
00:13:11,000 --> 00:13:11,960
fly,
154

155
00:13:12,080 --> 00:13:19,380
we can now go ahead and delete our fly method from our Bird class because not all birds can fly.
155

156
00:13:19,730 --> 00:13:26,540
And instead, we can say that our birds which can fly, our Eagle class, for example, well, they're going to
156

157
00:13:26,630 --> 00:13:36,330
adopt the CanFly protocol. And as soon as we do this, we get a error from Xcode telling us that you
157

158
00:13:36,350 --> 00:13:42,380
said that eagles can fly, but you haven't actually implemented a fly method in here.
158

159
00:13:42,920 --> 00:13:51,530
So if we click on this and we say, "Fix," well then it's going to add the fly method that is required by
159

160
00:13:51,530 --> 00:13:53,440
this CanFly protocol.
160

161
00:13:53,600 --> 00:14:02,330
And in here, I'm going to add a print statement that says, "The eagle flaps its wings and lifts off into
161

162
00:14:02,330 --> 00:14:02,930
the sky."
162

163
00:14:03,050 --> 00:14:07,700
So my eagle can fly because it implements the fly method,
163

164
00:14:07,700 --> 00:14:10,790
so it satisfies the requirements of my protocol.
164

165
00:14:10,850 --> 00:14:19,250
So the Eagle now has this protocol or this certification. And my penguin is not going to get this
165

166
00:14:19,250 --> 00:14:20,640
CanFly certification.
166

167
00:14:20,750 --> 00:14:21,940
It's just a bird.
167

168
00:14:21,940 --> 00:14:24,380
It has feathers, it has wings, it can swim,
168

169
00:14:24,380 --> 00:14:27,050
it can lay eggs, but it can't fly.
169

170
00:14:28,130 --> 00:14:32,710
But my airplane, on the other hand, now no longer has to be a class.
170

171
00:14:32,870 --> 00:14:38,030
It can be a struct because we actually don't need to inherit anything.
171

172
00:14:38,030 --> 00:14:43,790
Instead, it's also going to adopt the CanFly protocol.
172

173
00:14:43,790 --> 00:14:48,200
So protocols can be adopted by structures or classes.
173

174
00:14:48,200 --> 00:14:51,590
It's not like inheritance, it's not limited to classes.
174

175
00:14:52,220 --> 00:15:01,190
So now my airplane has this CanFly protocol, so it must implement the required method which is flying.
175

176
00:15:01,430 --> 00:15:02,820
If you say that you can fly,
176

177
00:15:02,960 --> 00:15:05,480
you must have an implementation.
177

178
00:15:05,480 --> 00:15:09,050
So "The airplane uses it engine to lift off into the air."
178

179
00:15:09,860 --> 00:15:18,050
And now in my flyingMuseum, rather than limiting my flyingDemo to using flying objects that are birds,
179

180
00:15:18,470 --> 00:15:21,030
I'm going to use a different data type.
180

181
00:15:21,200 --> 00:15:26,270
I'm going to use the CanFly protocol as a data type
181

182
00:15:30,650 --> 00:15:39,240
So now I'm saying that when my flyingMuseum puts on a flyingDemo, it requires a flying object
182

183
00:15:39,320 --> 00:15:47,090
that is something that adopts this protocol, because I know that when they adopt this protocol, they definitely
183

184
00:15:47,090 --> 00:15:49,580
have a fly method implemented.
184

185
00:15:49,640 --> 00:15:56,440
So I'm pretty sure that I'm not going to embarrass my museum by trying to demo a object that can't fly.
185

186
00:15:57,170 --> 00:16:05,030
Now, down here, my plane can no longer lay eggs because it's now just a simple structure that is an airplane,
186

187
00:16:05,180 --> 00:16:08,290
but it does adopt the CanFly method.
187

188
00:16:08,360 --> 00:16:19,130
Now, myEagle is able to fly. myPenguin is not able to fly, but it can do all of the other things that
188

189
00:16:19,130 --> 00:16:23,390
birds can do because it's still inheriting from the Bird class.
189

190
00:16:23,390 --> 00:16:33,920
But my airplane is now able to fly. And more importantly, when I put on my flyingDemo at myMuseum, I
190

191
00:16:33,920 --> 00:16:41,840
can now pass in myEagle which is able to go in here because it adopts the CanFly protocol.
191

192
00:16:41,840 --> 00:16:50,120
I can also pass in myPlane because it also adopts the CanFly protocol, but I can't pass in myPenguin
192

193
00:16:50,330 --> 00:16:55,280
because it does not adopt the CanFly protocol.
193

194
00:16:55,730 --> 00:17:03,050
So now instead of using inheritance where I'm saying my eagle inherits from the Bird class and my penguins
194

195
00:17:03,050 --> 00:17:10,850
inherit from the Bird class, and if birds are able to fly, then all the subclasses of birds, eagles and
195

196
00:17:10,850 --> 00:17:16,660
penguins all get this capability which it may or may not actually need.
196

197
00:17:17,300 --> 00:17:24,650
But on the other hand, when my airplanes actually need this CanFly ability, it can't really inherit
197

198
00:17:24,650 --> 00:17:31,710
from birds because it doesn't satisfy the other things that birds can do like laying eggs.
198

199
00:17:32,030 --> 00:17:37,360
Now, because we've learned about protocols, we can make our code much better.
199

200
00:17:37,790 --> 00:17:45,080
We can simply adopt that CanFly protocol everywhere where we need that capability.
200

201
00:17:45,080 --> 00:17:51,710
So our airplanes become a type that can fly, our eagles also become a type that can fly,
201

202
00:17:51,710 --> 00:17:57,620
and it means that we're assured that when we use an eagle or when we use an airplane, because it's marked
202

203
00:17:57,650 --> 00:18:03,720
as CanFly, it will definitely have a fly method implemented.
203

204
00:18:03,830 --> 00:18:12,310
This is our protocol in action. And as we mentioned, structures can adopt protocols,
204

205
00:18:12,310 --> 00:18:19,300
classes can adopt protocols, but you can also adopt multiple protocols. All you have to do is after the
205

206
00:18:19,300 --> 00:18:22,120
name of your structure or your class,
206

207
00:18:22,180 --> 00:18:27,650
you add a set of colons and you add your protocols one after the other
207

208
00:18:27,730 --> 00:18:29,780
separated by commas.
208

209
00:18:29,800 --> 00:18:34,760
Now, if you are creating a class and it needed to be able to inherit from a superclass,
209

210
00:18:34,780 --> 00:18:38,510
well, in this case, you're Superclass comes first.
210

211
00:18:38,530 --> 00:18:44,380
So it's going to be the name of the class, colon, the name of the Superclass, and then the protocols come
211

212
00:18:44,620 --> 00:18:52,620
after the Superclass separated, again, by commas. If you'd like to know more about protocols and how they
212

213
00:18:52,620 --> 00:18:54,210
work in detail,
213

214
00:18:54,210 --> 00:18:58,410
I recommend browsing through the Swift Language Guide on protocols.
214

215
00:18:58,410 --> 00:19:00,960
As always, you'll find a link in the course resources.
215

216
00:19:01,170 --> 00:19:08,340
But let's get back to our app. So now that we've seen what protocols are, we can see that all
216

217
00:19:08,340 --> 00:19:16,200
UITextField delegate is in fact just a protocol with a whole bunch of requirements. And those requirements
217

218
00:19:16,260 --> 00:19:23,610
are methods for implementing the textFieldShouldBeginEditing, the textFieldShouldEndediting, et cetera,
218

219
00:19:23,760 --> 00:19:24,940
and all of these things.
219

220
00:19:25,420 --> 00:19:33,240
But why is it a delegate? And how is it able to trigger all of these delegates? And what does it mean
220

221
00:19:33,340 --> 00:19:38,470
when we said the search field's delegate as this current class?
221

222
00:19:38,490 --> 00:19:43,400
Well, we'll explore all of that by doing another Deep Dive in the next lesson
222

223
00:19:43,500 --> 00:19:51,870
where we look at the delegate pattern using Swift protocols. So for all of that and more, I'll see you on the
223

224
00:19:51,870 --> 00:19:52,560
next lesson.
