0 1 00:00:00,240 --> 00:00:00,750 Hey, guys. 1 2 00:00:00,780 --> 00:00:03,300 Welcome to another Swift Deep Dive. 2 3 00:00:03,510 --> 00:00:09,400 And in this Deep Dive, we're going to learn more about using Optionals. 3 4 00:00:09,450 --> 00:00:17,310 Now previously, you've already been introduced to our ill-fortune cat, Fluffy. And because of our lack of understanding 4 5 00:00:17,310 --> 00:00:20,640 of optionals, we put her life in severe danger. 5 6 00:00:20,640 --> 00:00:25,680 So how can we make sure that we're not getting calls from the animal rights people and make sure that 6 7 00:00:25,680 --> 00:00:27,120 we treat our cat properly? 7 8 00:00:27,660 --> 00:00:30,480 Well, let's see how we can keep her out of harm's way. 8 9 00:00:31,050 --> 00:00:36,300 So what's going to happen in this Deep Dive is I'm going to walk you through five different ways of 9 10 00:00:36,300 --> 00:00:44,280 working with optionals in Swift including force unwrapping, checking for nil values, optional binding, the 10 11 00:00:44,280 --> 00:00:47,600 nil coalescing operator, and optional chaining. 11 12 00:00:47,850 --> 00:00:51,770 So that's a lot of new words, but let's get started. 12 13 00:00:52,080 --> 00:00:57,990 So I'm going to go ahead and create a new macOS command line tool just as we did before, 13 14 00:00:58,440 --> 00:01:01,830 and I'm going to call this OptionalsDemo. 14 15 00:01:01,830 --> 00:01:07,860 And when I go to my main.swift, I'm going to delete everything that's currently inside and I'm just 15 16 00:01:07,860 --> 00:01:10,600 going to use it as we do with our playgrounds. 16 17 00:01:10,620 --> 00:01:18,120 So first things first, I'm going to create a optional, so I call it myOptional and I'm going to give 17 18 00:01:18,120 --> 00:01:22,030 it a dtring data type. But, of course, to turn it into an optional, 18 19 00:01:22,050 --> 00:01:25,440 we just have to add the question mark at the end. 19 20 00:01:25,440 --> 00:01:32,580 Now, notice how the dtring data type is actually completely separate from the optional string data type. 20 21 00:01:33,000 --> 00:01:43,320 So if I was to give myOptional a value, say, "Angela," and if I create a constant which requires a string 21 22 00:01:43,320 --> 00:01:47,310 data type and I tried to set it to equal myOptional, 22 23 00:01:47,310 --> 00:01:54,360 this is not going to work because this expects a string and this has actually a completely different 23 24 00:01:54,360 --> 00:01:56,940 data type, an optional string. 24 25 00:01:56,940 --> 00:02:04,080 So how do we work with optionals? How can we turn it into an actual string that we can put into labels 25 26 00:02:04,080 --> 00:02:08,190 or buttons and manipulate in our code? 26 27 00:02:08,190 --> 00:02:14,850 Well, one of the simplest ways of working with optionals as we've seen is to simply just force unwrap 27 28 00:02:14,850 --> 00:02:16,020 the optional. 28 29 00:02:16,020 --> 00:02:22,230 But this, of course, requires us to really think hard and fast about whether if there's a case where we 29 30 00:02:22,230 --> 00:02:28,500 could be unwrapping the optional and it could actually have a nil value stored. Well, in that case, well, 30 31 00:02:28,560 --> 00:02:30,110 Fluffy gets it. 31 32 00:02:30,210 --> 00:02:35,700 In this case as well, if I go ahead and simply just unwrap the optional, then I make all the errors go 32 33 00:02:35,700 --> 00:02:42,900 away and I kind of am just telling Xcode that "You know what, I know better than you, and I know that 33 34 00:02:42,930 --> 00:02:50,540 this is never going to be nil." But what if myOptional was actually, in fact, storing no value at all? 34 35 00:02:50,550 --> 00:02:53,440 What if it was equal to nil? 35 36 00:02:53,460 --> 00:02:55,040 So in this case, yes, 36 37 00:02:55,140 --> 00:02:59,580 Xcode is not reporting an error, meaning we have no error at the moment, 37 38 00:02:59,580 --> 00:03:04,860 and our project build successfully. But when I run my code, it crashes. 38 39 00:03:04,860 --> 00:03:13,530 So in other words, I experience a crash at what we call runtime. And it crashes on the line where I'm 39 40 00:03:13,530 --> 00:03:19,900 force unwrapping myOptional because it was unexpectedly found to be nil. 40 41 00:03:19,920 --> 00:03:22,230 myOptional was equal to nil. 41 42 00:03:22,260 --> 00:03:26,970 So this is probably the least safe way of working with optional. 42 43 00:03:26,970 --> 00:03:33,210 It requires you to be really concentrated and search through your code to make sure that it can never 43 44 00:03:33,210 --> 00:03:34,850 be nil. 44 45 00:03:34,890 --> 00:03:40,560 So I know in this example, it seems super obvious because we're setting myOptional to nil, 45 46 00:03:40,560 --> 00:03:41,850 two lines earlier. 46 47 00:03:41,850 --> 00:03:47,550 But what if you were working on a more complex project with many files and many lines of code that you 47 48 00:03:47,550 --> 00:03:49,380 can't always keep track of? 48 49 00:03:49,380 --> 00:03:51,940 Well, in that case, it'll be a lot less obvious. 49 50 00:03:51,990 --> 00:03:54,880 So what else can we do? 50 51 00:03:54,900 --> 00:04:02,910 Well, a slightly safer way of working with optionals is to check to see if it's equal to nil. And if 51 52 00:04:02,910 --> 00:04:12,930 it's not, then we force unwrap it and use it in our code. If we had wrapped this line which is crashing 52 53 00:04:12,930 --> 00:04:20,860 our app at the moment, inside an "if" statement where we check if myOptional is not equal to nil, 53 54 00:04:21,250 --> 00:04:23,460 well, in that case, then we can use it. 54 55 00:04:23,910 --> 00:04:30,080 So now if I run my code again, then this line is just going to be skipped. 55 56 00:04:30,090 --> 00:04:31,290 How can we tell it skipped? 56 57 00:04:31,320 --> 00:04:41,030 Well, we can write an "else" statement or we say, "myOptional was found to be nil." 57 58 00:04:41,070 --> 00:04:46,680 So now let's run it again, and you can see we get "myOptional was found to be nil." 58 59 00:04:46,680 --> 00:04:51,330 So this "if" statement was skipped saving us from crashing our app. 59 60 00:04:51,690 --> 00:04:53,540 But here's a problem. 60 61 00:04:53,640 --> 00:04:56,160 This is, firstly, quite wordy. 61 62 00:04:56,250 --> 00:05:04,800 Even though I've already checked to make sure that myOptional is safe to work, I still have to use this 62 63 00:05:04,890 --> 00:05:10,070 exclamation mark to force unwrap the optional every single time. 63 64 00:05:10,110 --> 00:05:16,620 So if I wanted to create another constant, let's say text2: which was a string, and I wanted to be able 64 65 00:05:16,620 --> 00:05:24,300 to work with myOptional, well, again, I can't simply just use it without adding that exclamation mark 65 66 00:05:24,450 --> 00:05:31,740 where I force unwrap it. So this behavior where we are checking to see if the optional contains a nil 66 67 00:05:31,740 --> 00:05:39,820 value, and if it's not nil, then we work with it. It's so common while we're working with Swift optionals, 67 68 00:05:39,820 --> 00:05:44,890 that there is functionality that's built into optionals to handle this. 68 69 00:05:44,890 --> 00:05:47,190 And it's called optional binding. 69 70 00:05:47,190 --> 00:05:56,610 So in this case, what we do is we can write an "if let" to bind the value of the optional if it's not 70 71 00:05:56,610 --> 00:06:05,250 nil to a new constant, and within the curly braces of this "if" statement, we can now work with this safe 71 72 00:06:05,250 --> 00:06:09,540 version of the optional which has been unwrapped. 72 73 00:06:09,540 --> 00:06:18,240 So in this cas,e instead of writing "if myOptional is not equal to nil," I can write "if let safeOptional = 73 74 00:06:18,930 --> 00:06:21,490 myOptional." 74 75 00:06:21,480 --> 00:06:27,060 Well, in that case, safeOptional is going to equal the value of myOptional. 75 76 00:06:27,300 --> 00:06:30,780 But notice how safeOptional has a data type of string, 76 77 00:06:30,870 --> 00:06:33,880 while myOptional is an optional string. 77 78 00:06:34,080 --> 00:06:40,410 So now if I wanted to work with the value of myOptional, namely the word "Angela," 78 79 00:06:40,410 --> 00:06:47,460 well, I can now simply use the safeOptional, and you can see that if I decide to print my safe Optional 79 80 00:06:48,540 --> 00:06:56,370 and run my code, you can see that I get the value that's stored inside myOptional printed from the 80 81 00:06:56,370 --> 00:07:04,230 safeOptional. So it's just a way of performing that action of opening up the box seeing if there's anything 81 82 00:07:04,230 --> 00:07:05,160 inside. 82 83 00:07:05,160 --> 00:07:10,600 If it's nil, then simply go ahead and skip and go to the "else" statement. 83 84 00:07:10,710 --> 00:07:18,390 But if it's not nil, then we're going to put the value inside myOptional inside this new temporary constant 84 85 00:07:18,630 --> 00:07:26,620 which we can use inside the curly braces. But this simply just skips the optional 85 86 00:07:26,620 --> 00:07:28,960 if it's equal to nil. 86 87 00:07:28,960 --> 00:07:32,010 What if we wanted to provide it a default value 87 88 00:07:32,050 --> 00:07:36,060 in the case where myOptional is equal to nil, 88 89 00:07:36,100 --> 00:07:38,630 how can we do that? 89 90 00:07:38,740 --> 00:07:44,940 Well, there's another functionality of optionals that comes in really handy right about now. 90 91 00:07:44,940 --> 00:07:53,120 And it's called the Nil Coalescing Operator. And it's simply just two question marks next to each other. 91 92 00:07:53,150 --> 00:07:57,510 That's what it's called. And why is it the nil coalescing operator? 92 93 00:07:57,860 --> 00:08:03,340 Well, because what it does is it checks to see if the optional is nil. 93 94 00:08:03,680 --> 00:08:10,010 If it's not nil, then we're going to use that value. But if it is nil, then we're going to use the provided 94 95 00:08:10,130 --> 00:08:19,090 default value. So in our case, currently, my optional is nil, and I'm going to delete all of this "if" anc 95 96 00:08:19,090 --> 00:08:27,040 and "else" statement right now. And I'm going to try and, again, do the same thing, create a text constant that holds 96 97 00:08:27,040 --> 00:08:33,910 string data type, so real strings, not optional strings, and I want to work with my optional. 97 98 00:08:33,910 --> 00:08:43,330 Now, here I can say myOptional, well, if it has a value, then set that as the value of the text. But if 98 99 00:08:43,330 --> 00:08:50,050 it doesn't have a value, namely if it's nil, then we're going to use the double question mark, the Nil 99 100 00:08:50,050 --> 00:08:55,120 Coalescing Operator, and we're going to provide a default value. 100 101 00:08:55,240 --> 00:08:59,000 So "I am the default value." 101 102 00:08:59,380 --> 00:09:08,050 And now if we go ahead and print our text, then you can see that because myOptional was equal to nil, 102 103 00:09:08,590 --> 00:09:10,890 it was not set as the value of text, 103 104 00:09:10,900 --> 00:09:17,890 instead it's the default value after the nil coalescing operator that was set as the value of text, 104 105 00:09:17,950 --> 00:09:21,270 and that's what's getting printed right now. 105 106 00:09:21,340 --> 00:09:28,720 So those four things that we saw, force unwrapping, checking for nil values, optional binding, as well as 106 107 00:09:28,720 --> 00:09:36,790 the nil coalescing operator, cover all of the cases where our optional is just holding a simple value. 107 108 00:09:36,850 --> 00:09:43,750 Now, there are certain cases where instead of having a optional value, we actually have an optional struct 108 109 00:09:43,960 --> 00:09:45,600 or an optional class. 109 110 00:09:46,000 --> 00:09:49,540 Well, what do we do in that case? 110 111 00:09:49,540 --> 00:09:55,040 Let's say that our myOptional is no longer just a string. 111 112 00:09:55,180 --> 00:10:02,890 Instead, I'm going to create a struct which is called myOptional and it's going to have some properties, 112 113 00:10:04,480 --> 00:10:07,640 so property equals 123 113 114 00:10:07,690 --> 00:10:09,650 and some methods. 114 115 00:10:09,670 --> 00:10:14,790 So we have a method which is just going to print, 115 116 00:10:15,880 --> 00:10:22,130 "I am the struct's method." 116 117 00:10:22,140 --> 00:10:26,600 This is all very simple struct with a property and a method. 117 118 00:10:26,610 --> 00:10:36,630 Now, if I create a optional version, so myOptional and it's going to have myOptional as a data type, 118 119 00:10:37,080 --> 00:10:41,700 but it's an optional, so I haven't yet initialized it. 119 120 00:10:42,330 --> 00:10:49,140 So if I wanted to actually turn it into a real struct, then I would have to say myOptional equals 120 121 00:10:49,140 --> 00:10:49,830 MyOptional 121 122 00:10:49,830 --> 00:10:55,340 and, of course, that set of parentheses will turn it into a real value. 122 123 00:10:55,620 --> 00:11:00,950 So, that was the equivalent of giving the previous optional a value, right? 123 124 00:11:00,990 --> 00:11:02,160 It wanted a string, 124 125 00:11:02,190 --> 00:11:07,170 well, in this case, it actually wants the structure to be initialized. 125 126 00:11:07,440 --> 00:11:17,580 In this case, if I wanted to tap into the property of this optional or the method of this optional, then 126 127 00:11:17,670 --> 00:11:19,590 how would I go about doing that? 127 128 00:11:19,620 --> 00:11:28,140 So, let's say, I wanted to print myOptional.property. What would actually happen in this case? 128 129 00:11:29,040 --> 00:11:32,980 Well, I can't because this is an optional. 129 130 00:11:33,030 --> 00:11:39,390 So even though the property is not an optional, but because the struct is an optional, we can't actually 130 131 00:11:39,390 --> 00:11:48,760 proceed unless we either unwrap our optional. But if it was nil, then it's a little bit dangerous, right? 131 132 00:11:48,870 --> 00:11:56,520 Because if I turn that into a nil again and run my app, you can see that it's going to crash on this 132 133 00:11:56,520 --> 00:11:57,570 line. 133 134 00:11:57,690 --> 00:12:04,110 So even though the property itself is actually not an optional, it's just an integer, and we can see its 134 135 00:12:04,110 --> 00:12:05,480 value right here, 135 136 00:12:05,580 --> 00:12:11,670 we can't get to it if we haven't yet initialized this structure. 136 137 00:12:11,850 --> 00:12:16,800 So if it's equal to nil, then we can't proceed further. 137 138 00:12:16,830 --> 00:12:24,810 Now, how can we make this code safer? Well, then we would have to use something called Optional Chaining. 138 139 00:12:24,810 --> 00:12:31,620 So in this case, because our optional has some properties or methods that are access using the dot notation, 139 140 00:12:32,220 --> 00:12:38,110 in order to get to it, we add a question mark after the optional. 140 141 00:12:38,460 --> 00:12:46,620 And what this says is if this optional is not nil, then continue along this chain and go ahead and access 141 142 00:12:46,620 --> 00:12:50,110 that property. And we can do the same with methods as well. 142 143 00:12:50,130 --> 00:12:57,180 So if the optional had an associated method, then only when it's not nil do we actually execute that 143 144 00:12:57,180 --> 00:12:59,070 method. 144 145 00:12:59,260 --> 00:13:05,530 So in this case, if we replace this exclamation mark with a question mark, then when we run our app, it 145 146 00:13:05,530 --> 00:13:13,060 won't crash anymore, but this won't be equal to anything either because my optional is currently nil. 146 147 00:13:14,800 --> 00:13:24,700 So we can use this chaining method to access the properties and methods of optional, and this means that 147 148 00:13:24,820 --> 00:13:32,590 if our optional indeed was, in fact, initialized, so it now does have the property and methods set. Then 148 149 00:13:32,620 --> 00:13:41,230 when we run it, it will actually execute that method and it will print "I am the struct's method." 149 150 00:13:41,230 --> 00:13:47,200 So those are some of the five ways that you can use to work with optionals and we're going to be applying 150 151 00:13:47,200 --> 00:13:49,910 that in our app in the next lesson. 151 152 00:13:49,990 --> 00:13:52,510 So continue to the next lesson and I'll see you there.