0 1 00:00:00,840 --> 00:00:09,600 Hey, guys. Before we proceed onwards and start using Firebase Firestore to save our messages and send 1 2 00:00:09,600 --> 00:00:16,800 messages over for storage, I wanted to quickly take a moment to do a Swift Deep Dive on something that 2 3 00:00:16,800 --> 00:00:21,860 you might have seen in the last lesson that might still yet be a little bit confusing. 3 4 00:00:21,900 --> 00:00:24,790 So notice how in this line here, 4 5 00:00:24,810 --> 00:00:26,030 line 54, 5 6 00:00:26,190 --> 00:00:31,930 we created a cell by calling this method at dequeueReusableCell withIdentifier. 6 7 00:00:32,130 --> 00:00:38,310 We provided the identifier that comes from that cell that we created in the custom xib and we were 7 8 00:00:38,310 --> 00:00:46,080 hoping that our table view would just create this cell and slot it in. But right at the end here, 8 9 00:00:46,080 --> 00:00:50,250 we used this syntax "as!" 9 10 00:00:50,280 --> 00:00:50,830 MessageCell. 10 11 00:00:50,830 --> 00:00:56,760 What exactly does this do and what does it mean anyways? 11 12 00:00:56,850 --> 00:01:01,470 So in this Swift Deep Dive, I want to talk about exactly this. 12 13 00:01:01,470 --> 00:01:08,550 I want to talk about Type Casting because that's pretty much what that "as!" keyword does. 13 14 00:01:08,550 --> 00:01:18,540 Now, recently, I went to this workshop in Wales in the UK where we were casting sword from stone. So adding 14 15 00:01:18,540 --> 00:01:26,580 copper and tin into a crucible that was heated really hot, and then it was poured into this soapstone mold. 15 16 00:01:26,580 --> 00:01:35,900 And after the metal cools down, you end up creating a completely different shape, right? 16 17 00:01:35,940 --> 00:01:38,190 The shape of a bronze sword. 17 18 00:01:38,190 --> 00:01:43,980 Now, there's a lot more to creating a bronze sword including two days of polishing the sword in Wales 18 19 00:01:44,730 --> 00:01:51,900 which is freezing. But by the end, you create this beautifully, shiny mirror-like surface of a sword and 19 20 00:01:51,900 --> 00:01:53,540 it was really really cool. 20 21 00:01:53,610 --> 00:01:59,130 So how does this relate to what we're trying to learn? Now, as your coding and as you're looking at other 21 22 00:01:59,130 --> 00:02:07,420 people's code, you might notice these keywords as, as question mark, as exclamation mark, and is. 22 23 00:02:07,620 --> 00:02:14,470 And in this lesson, I want to explain to you what all of these keywords do, and when we would use them. 23 24 00:02:14,590 --> 00:02:20,830 So here I've set up a playgrounds which has something that you should already be familiar with from 24 25 00:02:20,830 --> 00:02:24,530 learning about classes and object-oriented programming 25 26 00:02:24,550 --> 00:02:31,360 in previous lessons. Here we've got three classes created, one called Animal, one called Human, and one 26 27 00:02:31,360 --> 00:02:32,980 called Fish. 27 28 00:02:32,980 --> 00:02:40,810 The animals all have a name and when you create any new animal, you initialize that new object with a 28 29 00:02:40,810 --> 00:02:42,150 name. 29 30 00:02:42,160 --> 00:02:47,560 Now, we've also created our Human class to be a subclass of Animal. 30 31 00:02:47,560 --> 00:02:49,730 It's inheriting from the Animal class. 31 32 00:02:49,750 --> 00:02:53,070 So, that means all humans also get to have a name. 32 33 00:02:53,110 --> 00:02:57,200 And, similarly, our Fish class is also inheriting from the Animal class. 33 34 00:02:57,220 --> 00:03:01,600 So these are what you would call subclasses and this is the superclass. 34 35 00:03:01,720 --> 00:03:08,140 Now, humans and fish can do all the things that animal can do which is why it inherits. 35 36 00:03:08,140 --> 00:03:14,050 But it can also do some specialized things like humans might be able to code and fish might be able 36 37 00:03:14,050 --> 00:03:16,040 to breathe underwater, 37 38 00:03:16,120 --> 00:03:18,890 so there's really nothing new in this code here. 38 39 00:03:18,940 --> 00:03:26,260 And if any of this looks unfamiliar, then I recommend having a quick revision of the lessons that we 39 40 00:03:26,260 --> 00:03:31,470 did on classes and objects and object-oriented programming. 40 41 00:03:31,570 --> 00:03:37,930 So, now that we've created our classes, let's go ahead and create some objects or instances from these 41 42 00:03:37,930 --> 00:03:38,920 classes. 42 43 00:03:38,920 --> 00:03:41,210 So let's say that I decide to create me, 43 44 00:03:41,230 --> 00:03:49,930 so Angela as a human, and we automatically get this initializer from the superclass Animal class, because 44 45 00:03:49,990 --> 00:03:56,260 human inherits from animal, and the name is going to be my name, of course. 45 46 00:03:56,260 --> 00:04:04,270 And then let's create another human, let's create Jack who's also a human and his name is Jack Bauer. 46 47 00:04:05,260 --> 00:04:09,500 And then, let's create somebody called Nemo. 47 48 00:04:09,520 --> 00:04:11,170 Nemo is a fish. 48 49 00:04:11,710 --> 00:04:14,830 And his name is Nemo. 49 50 00:04:14,830 --> 00:04:15,130 Great. 50 51 00:04:15,190 --> 00:04:21,700 So we've got three objects created from our classes, two humans and one fish. 51 52 00:04:21,790 --> 00:04:29,170 So let's say that we decided to create a array called neighbours, and these neighbours who live really 52 53 00:04:29,170 --> 00:04:36,740 close together are me, Jack, and Nemo. At this point, 53 54 00:04:36,850 --> 00:04:42,240 we've created an array using objects of different types, right? 54 55 00:04:42,520 --> 00:04:49,690 We've got Angela who has a type of human, Jack type of human, but Nemo has a type of fish, and they're 55 56 00:04:49,690 --> 00:04:57,520 allowed to fit into the same array because they have a common superclass Animal. 56 57 00:04:57,640 --> 00:05:03,220 So this neighbour's array is an array of Animal objects. 57 58 00:05:03,220 --> 00:05:12,280 That means if I was to pull out an item, say, the item at index 0 from this neighbour's array, you'll see 58 59 00:05:12,280 --> 00:05:15,010 that it still is an animal class. 59 60 00:05:15,040 --> 00:05:21,370 It doesn't revert back to the human class, even though we know that this is definitely of type Human 60 61 00:05:22,000 --> 00:05:27,420 because the array has mixed types. In order to store them in this mixed array, 61 62 00:05:27,490 --> 00:05:32,720 they have to find some commonality and that is, of course, the Animal superclass. 62 63 00:05:32,860 --> 00:05:38,680 So, now is where some of those type casting keywords come in handy. 63 64 00:05:38,770 --> 00:05:45,340 Previously, we've seen type casting in the sense that we've able to create a double, let's say, 64 65 00:05:45,340 --> 00:05:51,550 myDouble = 0.0, and let's just do a quick old option click check, you can see this is definitely a 65 66 00:05:51,550 --> 00:05:59,620 double data type. But if I wanted to create myDoubleAsAnInt, then I would use the int data type, 66 67 00:06:00,100 --> 00:06:07,500 open up a set of parentheses, and inside here, I get to put in myDouble, 67 68 00:06:07,900 --> 00:06:16,600 and it's able to cast this myDouble which has type double into something that has type int. 68 69 00:06:16,630 --> 00:06:25,270 Now, this is not really quite type casting, even though it does, in fact, change the type of myDouble into 69 70 00:06:25,390 --> 00:06:26,440 an Int. 70 71 00:06:26,620 --> 00:06:33,940 This is actually achieved through initialization. So if we take a look at the documentation 71 72 00:06:33,940 --> 00:06:35,260 for the Swift standard library, 72 73 00:06:35,260 --> 00:06:43,070 you can see that under the document for int it has a whole bunch of initializers. And one of these initializers 73 74 00:06:43,070 --> 00:06:48,110 is used for converting floating-point values such as doubles and floats. 74 75 00:06:48,340 --> 00:06:55,150 And this particular initializer is the one that's responsible for creating a new integer object from 75 76 00:06:55,360 --> 00:07:04,560 the double value, and it rounds towards zero. So without this initializer being created for Int, 76 77 00:07:04,620 --> 00:07:08,220 then we wouldn't be able to do this and change the data type. 77 78 00:07:09,150 --> 00:07:18,060 But in our case, if we wanted this neighbour1 to be treated as the human that it is, we have to do something 78 79 00:07:18,090 --> 00:07:19,380 different. 79 80 00:07:19,410 --> 00:07:23,630 So first thing we can do is we can check what data type it is. 80 81 00:07:23,640 --> 00:07:33,780 So, for example, we can say if neighbour 0, which is this one, is of data type Human, 81 82 00:07:33,810 --> 00:07:45,300 well, then we can print "First Neighbour is a Human." And if I go ahead and run this code, you'll see that 82 83 00:07:45,300 --> 00:07:52,000 what I get printed is, in fact, this because neighbour 0 is indeed a human. 83 84 00:07:52,020 --> 00:07:57,410 So we could perform this check and it tells us what data type it is. 84 85 00:07:57,510 --> 00:08:03,900 And you can do this if you wanted to, say, you could check if Jack is human. 85 86 00:08:03,900 --> 00:08:09,300 And the thing is we already know that Jack is human, and this is why when you try to write this code 86 87 00:08:09,330 --> 00:08:15,810 which is extremely obvious already without any sort of checking the Xcode compiler, it will actually tell 87 88 00:08:15,810 --> 00:08:22,830 you that this particular test is always going to be true, because there is no uncertainty about the data 88 89 00:08:22,830 --> 00:08:28,920 type of Jack. Whereas in this case, when we're tapping into the neighbour's array where everything is of 89 90 00:08:28,920 --> 00:08:38,550 type animal and we said, let's say, try to get the item at index 2, so 0, 1, 2, and we said, well, what if neighbours 90 91 00:08:38,600 --> 00:08:40,420 at index 2 is human. 91 92 00:08:40,440 --> 00:08:46,800 And then, in this case, we actually get nothing printed because neighbours at index 2 is in fact of type 92 93 00:08:46,890 --> 00:08:48,630 fish. 93 94 00:08:48,630 --> 00:08:57,270 So this "is" keyword, basically, allows us to have a object from a certain data type, and then check whether 94 95 00:08:57,270 --> 00:09:03,600 if that object is of that data type. So in this case, if we had a cell created from a UITableVieCell, 95 96 00:09:03,600 --> 00:09:09,420 and we check, if it is indeed that data type between the left-hand side of the "is" 96 97 00:09:09,420 --> 00:09:11,030 and the right-hand side of the "is." 97 98 00:09:11,070 --> 00:09:19,690 So this keyword is used for type checking. So let's say that I decided to go and create a function, 98 99 00:09:19,690 --> 00:09:22,020 let's call it find Nemo. 99 100 00:09:22,270 --> 00:09:28,870 And this function takes a input in the form of an array of Animal objects. 100 101 00:09:28,870 --> 00:09:34,020 So we're going to say findNemo, from, as the external parameter name, 101 102 00:09:34,180 --> 00:09:40,930 and then inside the function, we're going to refer to it as the animals. 102 103 00:09:40,930 --> 00:09:48,230 So, now we've got our function created and we're going to go ahead and loop through our Animal's array. 103 104 00:09:48,250 --> 00:09:52,740 So let's say for animal in animals. 104 105 00:09:52,780 --> 00:09:58,900 So in this case, we're looping through the array animals and for every single animal in that array, 105 106 00:09:58,900 --> 00:10:01,200 we're going to run the code in here. 106 107 00:10:01,270 --> 00:10:05,410 We can either simply just print animal.name. 107 108 00:10:05,410 --> 00:10:11,810 So this is pretty bog-standard sort of "for loop" kind of functionality that you've already learned about. 108 109 00:10:12,160 --> 00:10:20,380 And in this case, when the code runs, when I call findNemo from our neighbours array, go ahead and hit 109 110 00:10:20,380 --> 00:10:21,020 run, 110 111 00:10:21,200 --> 00:10:27,440 then you can see that we've got all the names of our animals in our neighbours array being printed out. 111 112 00:10:27,520 --> 00:10:29,420 So that's just a simple for loop. 112 113 00:10:29,440 --> 00:10:34,900 But what if I actually wanted to find Nemo inside this array of animals? 113 114 00:10:34,900 --> 00:10:44,440 Well, I could say that if the animal that we're currently looping on is of type fish, then that seems pretty 114 115 00:10:44,440 --> 00:10:45,100 suspicious, 115 116 00:10:45,100 --> 00:10:45,450 right? 116 117 00:10:45,460 --> 00:10:46,820 Maybe that's going to be Nemo. 117 118 00:10:47,200 --> 00:10:52,570 So let's go ahead and print that animal's name property. 118 119 00:10:52,630 --> 00:11:01,540 So, now what will happen if I run findNemo from neighbours is that we're going to get Nemo printed out 119 120 00:11:01,870 --> 00:11:08,320 because it's looping through all of the animals and checking each of them to see if they match the data 120 121 00:11:08,320 --> 00:11:14,740 type of fish. And when it does, then it prints out the animal name. 121 122 00:11:14,740 --> 00:11:21,850 Now, notice how, in this case, inside this set of curly braces, we're pretty certain that this particular animal 122 123 00:11:21,850 --> 00:11:25,420 that we've currently got access to is definitely a fish, 123 124 00:11:25,420 --> 00:11:25,720 right? 124 125 00:11:25,720 --> 00:11:32,050 Because we've checked if this animal is a fish before we actually trigger this block. But notice how 125 126 00:11:32,050 --> 00:11:37,900 in here, even though we're certain of that data type, we can't say something like, well, this a 126 127 00:11:38,260 --> 00:11:43,150 nimal.breatheUnderWater because that's what all fish data types can do, 127 128 00:11:43,160 --> 00:11:43,390 right? 128 129 00:11:43,390 --> 00:11:46,450 They have this functionality breatheUnderWater. 129 130 00:11:46,450 --> 00:11:51,190 But in fact it says, "Value of type 'Animal' has no member 'breatheUnderWater.'" 130 131 00:11:51,580 --> 00:11:58,150 So in this case, what's happening is that this particular animal, even though we know it is a fish, we've 131 132 00:11:58,150 --> 00:12:05,110 checked it. It still has that data type animal. So we're not able to tap into the specialized functionality 132 133 00:12:05,290 --> 00:12:07,150 of the fish. 133 134 00:12:07,150 --> 00:12:09,460 So what can we do in this case? 134 135 00:12:09,460 --> 00:12:16,990 Well, we can use something called forced down casting where we cast from the Animal class down to one 135 136 00:12:16,990 --> 00:12:18,460 of its subclasses. 136 137 00:12:18,550 --> 00:12:20,290 Like in this case, fish. 137 138 00:12:20,530 --> 00:12:29,700 So we could write something like let fish = animal as! Fish. 138 139 00:12:29,740 --> 00:12:35,980 So what this now does is it takes that animal which we've already checked and made sure is definitely 139 140 00:12:35,980 --> 00:12:44,590 of type fish, and we use the "as exclamation mark" to cast it down to one of the animals subclasses namely 140 141 00:12:44,590 --> 00:12:45,370 the Fish class. 141 142 00:12:45,940 --> 00:12:51,170 So, now with this fish created, we can now go ahead and tap into that method 142 143 00:12:51,190 --> 00:12:52,840 breathUnderWater. 143 144 00:12:52,930 --> 00:13:01,780 And when we run our code, you can see that Nemo is breathing underwater. So the "as exclamation mark" is 144 145 00:13:01,780 --> 00:13:07,630 used when, let's say, we've created a cell which is still the UI Table of your cell which, remember, 145 146 00:13:07,630 --> 00:13:09,100 is the superclass. 146 147 00:13:09,100 --> 00:13:16,480 And then we wanted to turn it into a subclass, for example, on message cell that you saw in our code earlier 147 148 00:13:16,480 --> 00:13:17,290 on. 148 149 00:13:17,350 --> 00:13:20,590 Well, in this case, we can use the "as exclamation mark." 149 150 00:13:20,590 --> 00:13:28,710 And now, this message cell object has converted or cast its data type into a subclass, 150 151 00:13:28,780 --> 00:13:34,150 so going down, and this is called forced downcast. 151 152 00:13:34,150 --> 00:13:39,720 Now, the problem with a forced downcast is that unless you're sure, 152 153 00:13:39,730 --> 00:13:45,130 say, for example, in this case, we're pretty sure that this particular animal that matches the Fish data 153 154 00:13:45,130 --> 00:13:48,090 type can be cast down into a Fish data type. 154 155 00:13:48,370 --> 00:14:00,280 But let's say that you decided to cast the neighbour at index 1, which is Jack, to a fish. 155 156 00:14:00,730 --> 00:14:02,780 So Jack's not going to like that very much. 156 157 00:14:02,950 --> 00:14:05,980 But let's go ahead and try it. 157 158 00:14:06,010 --> 00:14:08,240 Let's see what actually happens. 158 159 00:14:08,260 --> 00:14:10,770 So, you'll notice that I'm not getting any warnings, 159 160 00:14:11,020 --> 00:14:13,360 any problems, any errors at all 160 161 00:14:13,360 --> 00:14:15,930 because this is perfectly valid code. 161 162 00:14:16,120 --> 00:14:20,920 This is pretty much the same as if we did this, right? 162 163 00:14:20,920 --> 00:14:23,700 The compiler can't tell that it's going to fail. 163 164 00:14:23,740 --> 00:14:28,610 Now, we know because we can see right now what is at index 1, 164 165 00:14:28,660 --> 00:14:31,860 but let me just show you what happens when I try to run this code. 165 166 00:14:32,050 --> 00:14:37,450 You can see that it's at runtime, when your app is actually running in the user's hands, 166 167 00:14:37,570 --> 00:14:44,680 when this line of code is going to crash. And it tells us that it could not cast value of type Human 167 168 00:14:44,980 --> 00:14:46,920 to Fish. 168 169 00:14:47,110 --> 00:14:48,760 So that's the problem. 169 170 00:14:48,940 --> 00:14:54,280 Now, very often what happens is when we're dealing with data that we're getting back from the internet 170 171 00:14:54,370 --> 00:15:01,720 or from APIs, they often have a JSON or some sort of array where we're not really quite sure what's 171 172 00:15:01,720 --> 00:15:02,550 actually in it, 172 173 00:15:02,560 --> 00:15:02,940 right? 173 174 00:15:02,950 --> 00:15:04,780 Otherwise, we wouldn't be fetching it. 174 175 00:15:04,780 --> 00:15:12,940 So in these cases, unless you're certain that this cast is going to work, then a better option is to add 175 176 00:15:13,270 --> 00:15:17,200 a question mark, instead of an exclamation mark. 176 177 00:15:17,290 --> 00:15:26,020 But what this does is it turns this object that's cast from this object to a Fish data type into an 177 178 00:15:26,050 --> 00:15:27,080 optional. 178 179 00:15:27,080 --> 00:15:31,640 So, now if I check this data type, you can see it's a fish question mark. 179 180 00:15:32,080 --> 00:15:38,290 So that means if you wanted to be able to do something like a fish.breatheUnderWater, then you 180 181 00:15:38,290 --> 00:15:44,710 will either have to use the optional chaining, like how it's inserted this question mark here which says, 181 182 00:15:44,710 --> 00:15:48,310 basically, if fish is not nil, then call this method. 182 183 00:15:48,310 --> 00:15:57,370 Alternatively, you would have to use a optional bind, say, if let the neighbour at index 1 can be cast as 183 184 00:15:57,370 --> 00:16:00,590 a fish, well then go ahead and run this code. 184 185 00:16:00,610 --> 00:16:07,750 Now, if I run this code again, you'll notice that it doesn't actually crash anymore because this is actually 185 186 00:16:07,750 --> 00:16:14,130 being skipped. And in fact, I can add an 'else" statement to print that "Casting has failed." 186 187 00:16:15,090 --> 00:16:21,750 So let's run that code and you can see that it's the "else" case that gets triggered in this block of 187 188 00:16:21,750 --> 00:16:32,270 code. So the "as" keyword is a slightly safer way of performing this down casting capability, instead of 188 189 00:16:32,270 --> 00:16:36,860 simply just saying, "Yeah, yeah, you know cell is definitely gonna be convertible to message sell in all cases" 189 190 00:16:36,860 --> 00:16:43,400 when you're not sure it's better to actually use a "as" question mark. 190 191 00:16:43,400 --> 00:16:52,370 So this way, we only actually do the casting if it actually can be cast as the subclass. Whereas in this 191 192 00:16:52,370 --> 00:16:59,610 case, we can be pretty certain to downcast because we know that the animal is definitely a fish. 192 193 00:16:59,660 --> 00:17:05,270 Now, in other cases where you've written the code, say, you've created the array, you know what each of 193 194 00:17:05,270 --> 00:17:14,030 the items are, then you can also make the case that a forced downcast, in this case, is probably okay. 194 195 00:17:14,030 --> 00:17:21,950 So, the last keyword I want to show you is this thing called "as." For example, in this case, we know that this 195 196 00:17:22,040 --> 00:17:26,440 fish object has data type fish, right? 196 197 00:17:26,660 --> 00:17:32,090 But what if we wanted to turn it back into the data type of its superclass? 197 198 00:17:32,570 --> 00:17:43,160 Well, we can say, let animalFish = fish as, with no question mark or no exclamation mark, 198 199 00:17:43,160 --> 00:17:46,770 and then we can cast that to one of its superclasses. 199 200 00:17:46,790 --> 00:17:53,670 So in this case, we could say, turn it into an animal. And this takes the object which has the class Fish 200 201 00:17:54,270 --> 00:17:57,390 and raises up to the animal superclass. 201 202 00:17:57,390 --> 00:18:04,890 So now this animalFish has type animal, whereas it came from this object fish which had the subclass 202 203 00:18:04,980 --> 00:18:07,350 fish data type. 203 204 00:18:07,350 --> 00:18:15,630 So the "as" keyword by itself is simply used to raise a object to its superclasses type. 204 205 00:18:15,660 --> 00:18:20,530 So it's another form of casting but it's, perhaps, use a little bit less frequently. 205 206 00:18:20,700 --> 00:18:25,950 And the reason why it doesn't need to have an exclamation mark or a question mark is because when you 206 207 00:18:25,950 --> 00:18:31,530 take a subclass object and you convert it into a superclass, it's never going to fail. 207 208 00:18:31,530 --> 00:18:38,640 This is always going to work as long as this particular object that you're trying to cast is, indeed, 208 209 00:18:38,670 --> 00:18:42,780 inheriting from the data type that you're trying to cast it to. 209 210 00:18:42,780 --> 00:18:47,340 In other words, the "as" keyword is used to perform an Upcast. 210 211 00:18:47,460 --> 00:18:53,460 That said of casting is performed a lot less frequently than down casting, but it belongs in the set 211 212 00:18:53,520 --> 00:18:54,970 of as, as, as, 212 213 00:18:54,990 --> 00:18:57,430 so it's a good idea to talk about it. 213 214 00:18:57,690 --> 00:19:02,850 Now, the very last thing I want to talk to you about is some of these strange data types that you 214 215 00:19:02,850 --> 00:19:04,540 might have come across. 215 216 00:19:04,590 --> 00:19:10,710 This is a topic that's closely related type casting and working with types in general. 216 217 00:19:10,710 --> 00:19:14,890 Sometimes you don't want to be specific about the data type that you're working with. 217 218 00:19:14,940 --> 00:19:20,970 Sometimes you'll want flexibility and you'll want your code to accept a range of different data types. 218 219 00:19:21,810 --> 00:19:31,470 And in Swift, we have something called "any" which encompasses all objects, so objects derived from classes, 219 220 00:19:31,530 --> 00:19:36,490 from structs. Basically, it can be any data type just like the name. 220 221 00:19:36,720 --> 00:19:46,710 Now, within that group of any data type, there is a subclass of AnyObject data types, and these are object 221 222 00:19:46,800 --> 00:19:49,800 that have to be derived from classes. 222 223 00:19:49,800 --> 00:19:57,390 So sometimes you'll see certain protocols that have a requirement where only an object created from 223 224 00:19:57,390 --> 00:20:00,510 a class can actually conform to that protocol, 224 225 00:20:00,540 --> 00:20:08,550 so they might use this data type "AnyObject" in that way to limit things to work with classes. And then 225 226 00:20:08,670 --> 00:20:14,700 even more specialized are these "NSObjects" which are the objects that are created from the foundation 226 227 00:20:14,700 --> 00:20:15,570 classes. 227 228 00:20:15,630 --> 00:20:22,860 So remember how we often import foundation. Well, inside that foundation module, we get access to NSNumber, 228 229 00:20:22,920 --> 00:20:29,730 and as dates, file manager, and a whole bunch of other objects that Apple has created. 229 230 00:20:29,730 --> 00:20:36,910 So if we were to head back to our code and where we've got this array of objects, right? 230 231 00:20:36,990 --> 00:20:43,980 If I was to create, say, just like an integer, right? Let's call it num and let's make it equal to 12, 231 232 00:20:44,330 --> 00:20:50,460 and I tried to add this number to our array of neighbours, then you'll see that it's not really going 232 233 00:20:50,460 --> 00:20:56,660 to allow me to do that because there's absolutely no commonality between all of these guys. 233 234 00:20:56,700 --> 00:21:03,210 The only way that I can do this is actually by making my array of type Any. 234 235 00:21:03,300 --> 00:21:10,920 So if I had an array of type Any, then this is gonna be fine. "Any" allows us to mix any type, literally. 235 236 00:21:11,640 --> 00:21:19,020 In this example, we're mixing the human type, the fish type, and an integer type because Angela and Nemo 236 237 00:21:19,230 --> 00:21:25,910 are instances created from classes, whereas the integer is created from a structure. 237 238 00:21:26,010 --> 00:21:35,020 So this keyword "any" allows us to mix classes and structures or any other data type. So what happens when 238 239 00:21:35,020 --> 00:21:38,110 I change Any to AnyObject? 239 240 00:21:38,110 --> 00:21:39,620 Now, we get an error. 240 241 00:21:39,640 --> 00:21:40,060 Why. 241 242 00:21:40,510 --> 00:21:46,060 Well, the reason is that AnyObject restricts the types to those that come from classes. 242 243 00:21:46,060 --> 00:21:51,580 So in other words, structures are no longer allowed to play and they're no longer allowed to be part 243 244 00:21:51,640 --> 00:21:56,140 of our collection. And integers, strings, and doubles, 244 245 00:21:56,140 --> 00:22:02,740 these are all structures which is why we get this error. And I can show this to you in another way. 245 246 00:22:03,320 --> 00:22:10,210 Let's say there our fish Class was instead a structure and structures, of course, don't have inheritance, 246 247 00:22:10,220 --> 00:22:12,980 so I have to delete all of this. But there we go, 247 248 00:22:12,980 --> 00:22:18,650 we've got our Nemo which is created from fish. But right now, if I try to run this, this also gives me an 248 249 00:22:18,650 --> 00:22:19,140 error. 249 250 00:22:19,160 --> 00:22:27,470 It says that Nemo which has type 'Fish' can't be converted to AnyObject because AnyObject requires that 250 251 00:22:27,470 --> 00:22:35,900 the object be created from a class, like the Human class, where Angela and Jack are created from. But Nemo 251 252 00:22:35,900 --> 00:22:40,610 is created from the Fish struct which is not an AnyObject. 252 253 00:22:40,610 --> 00:22:47,270 Now, let's say we changed this to NSObject which means that we're even more limited as to what can 253 254 00:22:47,270 --> 00:22:49,000 go into our array. 254 255 00:22:49,220 --> 00:22:56,060 Neither Angela, Jack, or Nemo actually fit these criteria because we need to use one of the classes and 255 256 00:22:56,060 --> 00:22:58,630 foundation that's created by Apple. 256 257 00:22:58,640 --> 00:23:05,360 So, for example, let's say I decide to create a number that's created from the NSNumber class and I set 257 258 00:23:05,360 --> 00:23:06,730 it to equal to 12, 258 259 00:23:07,130 --> 00:23:17,360 or let's say I create a word that's created from the NSString class and I set it to ABC, well, these items 259 260 00:23:17,420 --> 00:23:18,430 can go in here, 260 261 00:23:18,440 --> 00:23:18,680 right? 261 262 00:23:18,710 --> 00:23:25,250 I could put "num" and I could put "word" and if I take out "Nemo," then you'll see that this is perfectly 262 263 00:23:25,250 --> 00:23:25,700 valid. 263 264 00:23:25,700 --> 00:23:33,900 These are both NSObjects that can match this particular requirement. But as soon as I try to add 264 265 00:23:33,900 --> 00:23:42,270 in a struct, for example, on Nemo, or if I try to add in a Human, which is created from our class, none of 265 266 00:23:42,270 --> 00:23:43,680 these will be allowed. 266 267 00:23:44,160 --> 00:23:51,570 So, essentially, depending on how strict your criteria is, you can actually go through these very broad 267 268 00:23:52,680 --> 00:23:53,430 types: 268 269 00:23:53,430 --> 00:24:01,320 Any, AnyObject, and NSObject, and allows you to create collections of items that are more broad than 269 270 00:24:01,320 --> 00:24:04,870 just the classes that we've created ourselves. 270 271 00:24:04,920 --> 00:24:09,950 So, now that you've learned all about typecasting, I have a small reading assignment for you. 271 272 00:24:10,110 --> 00:24:15,870 So if you have some time, I recommend heading over to this link which you'll be able to find in the course 272 273 00:24:15,870 --> 00:24:16,760 resources, 273 274 00:24:16,950 --> 00:24:23,280 and just having a read of this page on typecasting to get a little bit more background information and 274 275 00:24:23,580 --> 00:24:28,780 learn a little bit more about this topic. So consider it an optional assignment. 275 276 00:24:28,800 --> 00:24:36,450 All right, in the next lesson, we're going to be using Firebase to save and retrieve data from the Firebase 276 277 00:24:36,510 --> 00:24:37,770 Cloud Firestorm. 277 278 00:24:37,950 --> 00:24:45,540 And when we retrieve the data back, we'll have to use some form of casting in order to convert it into 278 279 00:24:45,540 --> 00:24:48,300 a data type that has the capabilities that we need.