Guys, welcome to yet another Swift Deep Dive. 1
And in this Deep Dive, we're going to talk about structures. Now, structures helps us create custom data 2
types. 3
So whereas previously we saw that there were loads of basic data types that comes prebuilt along with 4
Swift. For example, Strings, Ints, Floats, Doubles, Boolean, Arrays, and Dictionaries, you name it. 5
There's a whole lot of different prebuilt data types. 6
But what if we needed our own data type something that groups gather related properties and behaviors. 7
For example, our quiz questions. 8
Currently, we have a 2D Array which basically forces these two pieces of data, the answer and the question, 9
to be associated with each other. 10
But, actually, these are two properties of a question, right? 11
The text of the actual question, as well as the correct answer of a question, 12
those should really somehow be interlinked together. And in order to do that, we could use a structure. 13
So we create a structure by using the struct keyword, and then we give it a name. 14
Now, notice how the names of struct are a little bit different compared to methods or properties. 15
When you're creating a struct, the name that you give it has to be capitalized even at the beginning. 16
So that way, you can tell that it's actually a data type. 17
Similar to how our string Int or Float data types, all start with a capital letter. 18
Let's go ahead and create our own structure in playgrounds. So let's say that I was to create the structure 19
of a town. 20
Well, I would start by writing the struct keyword, and then I would give my structure a name. 21
So let's just call it Town. And then I'm going to open a set of curly braces inside of which I can define 22
the properties of my town. 23
So what other kind of properties a town might have? 24
Well, it might have a name, right? 25
So let's create a constant using the "let" keyword and give this constant a name of names, so the name of the 26
town. And then I'm going to give it a value, so let's call it "Angelaland." 27
Now, let's think. What are some other properties that a town might have? 28
Well, it probably has some citizens, right? But in this case, I'm going to create a variable and the variable is 29
gonna be called citizens and it's going to be equal to an array. 30
So these are all the people that live in Angelaland, and it will be myself and, let's say, Jack Bauer, 31
my ultimate hero. 32
And so now that we've got the citizens who live in the town, the name of the town, the last property I'll 33
add are the resources in this town. 34
So let's say that we had some "Grain," maybe 100 bags of grain, some "Ore." I think I've been playing a little 35
bit too much of a Settlers of Catan recently. 36
That's all I can think about. 37
Let's say we had 42 blocks of ore. I'm not sure what's the unit of count of ore. And then, let's say we 38
had some "Wool." 39
Notice how here I'm creating a dictionary, 40
So it's a variable called resources which is a collection of dictionary items. 41
So we've got our key and our value. 42
So a 100 bags of grain, 42 bags of ore, 75 bags of wool. 43
And these three properties are now all packaged together into my Town structure. Now that we've created 44
our struct, 45
it's time to actually initialize it. By initializing, I mean creating an actual object that we can use. 46
So to create an actual town from our town structure, all that we would need to do is create a new var 47
and this var will be called myTown. 48
Now, this myTown is going to be the actual town created from this structure. And to express that in code, 49
we would write var myTown = Town, and then a set of parentheses. 50
So now what I've done is I've created a new copy of this town structure and it's held within the variable 51
of myTown. 52
So that means I can actually use this object myTown and I could access the properties of myTown. 53
For example, I could print myTown. And to access the properties, I would use the dot notation. 54
So as soon as I write dot, you can see all the things I can tap into. And let's say that I wanted to print 55
"Who are the people who live in my town?" 56
I'm going to print myTown.citizens. And currently, it's just me and Jack Bauer. 57
Now, I can tap into some of the other properties as well. 58
So, for example, if I wanted to use my string interpolation to get hold of myTown.names or the name 59
property of my town. 60
And then, let's say, myTown has-- Let's do like a little report, shall we? 61
How many bags of grain have I got? 62
So then it would be myTown.resources. 63
And then we would use the square brackets to access the "Grain" key, and then we could say, well, it has 64
this many bags of grain. 65
So now if I run my code, you can see that these are the citizens and Angelaland has 100 bags 66
of grain. 67
That's a pretty good, pretty good town 68
if I might say so myself. Now, with the object that we've created, myTown, we don't have to limit ourselves 69
to just retrieving data or retrieving the values or properties of this object. But we can also add and 70
modify it. 71
So for example, if let's say that my town has a new citizen, let's say that Keanu Reeves decided to 72
move into this wonderful town. 73
Well, then I might say myTown.citizens to access the citizen property of myTown. 74
Well, then I can append so add something to my citizens array, and the name that I'm going to spend is, 75
of course, our new neighbor, Keanu Reeves. So there's three of us now in our town. And I can print, for example, 76
myTown.citizens.count. And when I do that, you can see that after I've added Keanu Reeves to 77
the citizens of myTown, we now have three people living there. Whereas previously, when I printed 78
myTown.citizens, we only had two people. 79
Now, so far, the structure of our town only defines the properties of a town. 80
So town should have names, each town should have citizen, and they should have resources. But we can also 81
define a behavior of our structure so we can make towns be able to do things like build barricades and 82
get everybody inside and we sort of eat all our 100 bags of grain. And to do that, we would simply just 83
create a function within our structure. 84
So let's say, we created a function called fortify. And now inside this fortify function, we could simply 85
just for ease of use, we'll just print "Defenses increased!" So now our town structure has properties and 86
it has something that it can do. 87
Now, when we have a function that's associated with a structure, well, then the name for it is actually 88
called a method. 89
So if you hear the words functions or methods, when people refer to it on StackOverflow on line, just 90
know that they're both referring to this same thing. 91
The thing that we create with a funky word and it defines some behavior inside the curly braces, 92
but if this behavior was defined inside the curly braces of a structure or a class, then we would call 93
it a method. 94
But if it was sort of standalone, free floating around somewhere, well, then we would call it a function. 95
At the end of the day, 96
it's just defining behavior, something that it can do. 97
But now I can trigger this method or this functionality that my town has by writing myTown,B 98
so this is the actual object that can do things and has properties, dot, 99
and I'm going to make it do something. 100
Now, notice here that this "M" stands for method. 101
And if I hit enter, then my town is going to fortify itself 102
when I run that line of code. And we can see that myTown has its defenses increased, so it's able to 103
perform an action or a behavior. When we create a struct in our code, we're essentially creating a blueprint 104
for an eventual object that will get created from our blueprint. 105
And in this blueprint, we get to plan ahead for how this eventual object will be. 106
For example, we create variables, and when our variables live inside a struct, that variable is associated 107
with our struct and it's known as a property of that struct. 108
Similarly, we've created functions inside our struct. And when functions are created inside a struct, they're 109
known as a method. 110
So you can consider these properties as a way of defining what this eventual object created from the 111
struct will be like. 112
So its attributes or its properties and the methods can be thought of as what the objects can do. 113
So in the context of an actual car object that gets created from a car struct or car blueprint, 114
well, those properties might be things like the color of the car or the number of seats it has, or the 115
number of doors it has, or whether if it's a hatchback or a sedan, something that describes what this 116
eventual object is going to be like. And the methods for the car, 117
well, those are things that the car object can do, 118
so things like drive or brake, or switch on the indicator lights. And it's through describing these properties 119
and methods of the objects that will get created when our app is running. 120
So these objects are invisible. We can't see them. We can't touch them. But we can plan for how they will 121
behave and how they will look 122
by creating these properties and methods. So when we were defining our town struct, we were writing the 123
blueprint for the eventual object that will get created. And we can take our blueprint and initialize 124
it which turns it into the actual object. 125
In this case, maybe an actual car. 126
But what do I mean by that? What is initializing mean and what does the code actually look like? 127
Just like we would create a function, 128
we create our initializer in a pretty similar way. We have are parentheses for the inputs that gets 129
passed over. 130
We have our curly braces for the implementation or the code for how to initialize our structure. 131
So how does the initializer get used? 132
Well, the initializer gets triggered when we create our object from our blueprint. But why do we have 133
initializers in the first place? 134
What's the purpose of the initializer? 135
Well, suppose you want to create the next civilization or Settlers of Catan video game, 136
well, in that case, you're going to need more than one town, 137
right? 138
Well, in addition, to Angela Land, you'll need Athens, Beijing, and New Delhi, and many, many more, but all 139
of these places are different. 140
They have a different name, different citizens, and different resources. 141
Wouldn't it be nice if we could use our struct to act as a blueprint for all of these towns, but still 142
be able to customize each town? 143
Well that's where the initialize it comes in. 144
Let's head back into playgrounds to see this in action. Let's delete everything we have here currently 145
and just be left with our structure. 146
Now, I'm also going to delete the values of these properties to keep my town very generic. So the name 147
is going to be a string data type. 148
The citizens are gonna be an array of strings and the resources are going to be a dictionary made up 149
of strings for keys and integers for values. 150
So now my town structure has blank properties for each of these attributes and I can now define a custom 151
property 152
every time I create a new town. 153
But before we do that, we need to create the initializer. 154
So I'm just gonna write "init." And when my swift code snippet symbol comes up, I'm just gonna hit enter. 155
And inside the place holder which says "parameters," I'm going to add some input parameters, so when 156
I initialize a new town from myTown structure, 157
I'll be able to use these inputs to fill in my properties. 158
The first one is going to be townName which is going to be of type String. 159
Next, it's going to be the people of the town which are going to be an array of strings. 160
And finally, I've got the stats for my town which is going to be a dictionary comprised of String keys 161
and Integer values. 162
So that's all three inputs that I need for my initializer. 163
And inside the initializer, what I'm gonna do is I'm going to set my town's name property to equal 164
whatever got passed in as the townName, and then I'm going to set my citizens property to equal whatever 165
got passed in as the people of the town. 166
And finally, my resources property is going to be populated with these stats that have been inputed for 167
this town. 168
So now if we're creating our town with an initializer, the way that we would do that is, let's create 169
a variable code, 170
I don't know, another town, and let's set it to equal a town created with our Town blueprint. 171
And then, once we open a set of parentheses, you can see all of those input parameters show up, townName, 172
people, and stats. 173
So if we hit enter, we can use these placeholders and you can hit tab to go between them, and we need 174
to provide some values in each of these positions. And we can also see what type of data we need to provide. 175
So the first one for the town name has to be a String. 176
So let's call this "Nameless Island." And the people who live in this Nameless Island will just be one 177
guy and it's gonna be Tom Hanks. 178
And for the stats of this town that I'm creating, it's just gonna have a whole lot of coconuts. 179
And let's say, it's got 100 coconuts on this Nameless Island. 180
So now that I've created another town, I can do exactly as what I've done before, I can tap into my object, 181
the anotherTown. So remember the object is the thing that's actually created from the blueprint. 182
And I can, of course, print the properties, say, the citizens or the name, I can call or trigger the methods 183
or the behaviors that the town can do, namely fortify itself, but I can also, of course, tap into, let's 184
say, our citizens. And then just as we did before, we can append a new element which happens, in this case, 185
to be a beach ball who's going to join the citizens of Nameless Island, and he's gonna be called Wilson. 186
So now we have another town which is an object created from the Town blueprint with all of these properties 187
that we've specified when we created the town using the blueprint. 188
And we're able to use this object just as we did before to tap into its properties or to manipulate 189
or change some of those properties. 190
And we can, again, if we wanted to, now print our anotherTown, so our objects property. 191
Let's print and see who lives in this town. 192
So this time it prints, there's "Tom Hanks" and there's "Wilson" on Nameless Island. 193
Now, notice how I'm twisting these names so that they don't overlap with the names I've got as the properties 194
of my town. Because in reality, it would be much easier for me to just name this name, 195
name these citizens, and name these resources. 196
But now, when I initialize it, I have to set the name equal to name, and the citizens equal to the 197
citizens, and the resources equal to the resources. 198
Now, it kind of makes sense if you really think about it. 199
So I'm saying that the name property of myTown structure should be set to equal the name that got passed 200
in as the input parameter. 201
But this code is very confusing because this name matches exactly this name. 202
Now what else can I do? 203
Well, I can make it really explicit which one I'm talking about whether if it's the property or whether 204
if it's the input here by simply adding the word "self" in front. Now, you might have already come across 205
this keyword "self" and we haven't really gotten round to explaining it and this is the perfect time 206
to really explain it. Because the "self" keyword refers to the eventual object that will be created from 207
this structure blueprint. 208
Whereas right now, we're saying self.name referring to the property name of our structure town. 209
Well, eventually, when we try to initialize our town, that "self" is going to refer to the object that's initialized, 210
so, for example, the anotherTown. By adding that "self" keyword in front of all of these properties, I can 211
now easily differentiate them by saying, well, self.name, of course, refers to my town's name property, 212
self.citizens, 213
of course, refers to my town's citizens. 214
And you can view this "self" keyword as referring to the structure. 215
Now, that I've changed the parameter names of my initializer for my town structure, well, I also have to 216
change them here, 217
right? 218
So this is what this error is about. 219
It says that the labels should be the name citizen resources, but instead, we have townName, people, and 220
stats. So we can go ahead and click Fix for it to change it for us to the ones that we specified in the 221
initializer the and all the errors go away. 222
But from now on, also, when we create, say, let's create a ghostTown from our Town blueprint, 223
and when I hit enter, you'll see that these are now the parameter names 224
I have to provide. Let's create all ghostTown which is going to be called 225
"Ghosty McGhostface," and the citizens are none. 226
There's nobody living here because it's a ghost town. 227
And the resources are--just got like a lot of "Tumbleweed" of 1, just tumbling around in our ghost town. 228
So notice how right now I've got one object created from my Town blueprint which is called anotherTown. 229
And in there, we've got Tom Hanks with a bunch of coconuts, and we've got another town called ghostTown 230
which, again, we've created from exactly the same blueprint. 231
But this town is completely different, 232
it's got a different name, 233
it's got no citizens, and it's got just a single tumbleweed, "Tumbleweed." 234
So now when we tap into our objects, let's say that in another town, we've got a new citizen who's moved 235
in, so we'll append "Wilson" to that town. 236
Whereas in the ghostTown, well, nothing really happens. 237
But let's say that we just decided to fortify the town. 238
Notice how here I'm tapping into different objects that have essentially been created from the same 239
blueprint. 240
And when I hold down option, click on each of these objects, you can see that they both have the same 241
data type. 242
They're both created from the town structure. But they are really different from each other. 243
They have different names, different citizens, different resources, 244
and I can specify which one I want to manipulate, which one I want to change, whose properties I want 245
to tap into. 246
And now, we've got essentially a whole bunch of things that we can play with by using this blueprint 247
as a starting point. 248
So now that you've learned all about structures, it's time to test your knowledge in the structures assignment. 249
So head over there before you continue in the project. 250
So head over there before you continue in the project. 251
And once you're back, I'll see you on the next lesson.