0 1 00:00:00,870 --> 00:00:04,390 Welcome to Part 2 Dicee in SwiftUI. 1 2 00:00:04,440 --> 00:00:08,880 In the last lesson, we got our app looking exactly the way we wanted to. 2 3 00:00:08,880 --> 00:00:11,660 So, now it's time to add some functionality. 3 4 00:00:11,790 --> 00:00:16,970 For instance, how can we change the dice faces every time the Roll button is pressed. 4 5 00:00:17,760 --> 00:00:25,920 Well, we can start out by going to the top of our ContentView struct and creating some variables. 5 6 00:00:25,920 --> 00:00:32,200 So one variable I'll call the leftDiceNumber set out to equal 1. 6 7 00:00:32,280 --> 00:00:36,350 And I'm also going to create the rightDiceNumber 7 8 00:00:36,780 --> 00:00:39,630 and it's also going to be equal to 1. 8 9 00:00:39,660 --> 00:00:45,840 So these numbers are what I'm going to use to set the image that's in my DiceView. 9 10 00:00:46,290 --> 00:00:54,360 So remember that this "n" property is the one that's going to initialize our image with a particular 10 11 00:00:54,360 --> 00:00:56,730 dice number. 11 12 00:00:56,730 --> 00:01:00,570 So if that end was equal to 1, then that's what we see on screen. 12 13 00:01:00,570 --> 00:01:05,010 If it's equal to five, then it's the dice face with five dots on it. 13 14 00:01:06,420 --> 00:01:15,120 So instead of using the hardcoded one, I'm going to change that to use our variables, leftDiceNumber 14 15 00:01:15,630 --> 00:01:18,180 and rightDiceNumber. 15 16 00:01:18,180 --> 00:01:23,310 So right now, if we refresh our code, you'll see that nothing has changed. 16 17 00:01:23,310 --> 00:01:30,890 It still works exactly as it used to. But our Roll button still doesn't do anything. 17 18 00:01:30,930 --> 00:01:38,310 So remember, previously, I mentioned that the button's action property is the area where we're going to 18 19 00:01:38,310 --> 00:01:42,460 determine what should happen when the button gets pressed. 19 20 00:01:42,570 --> 00:01:46,760 Well, inside this area, we can write some code. 20 21 00:01:46,920 --> 00:01:55,260 So what we want to happen is to generate some random numbers between 1 and 6 to replace the number that's 21 22 00:01:55,260 --> 00:01:59,160 inside the leftDiceNumber and the rightDiceNumber. 22 23 00:01:59,160 --> 00:02:08,730 So inside these curly braces, I'm going to set the leftDiceNumber to equal a random integer, 23 24 00:02:08,760 --> 00:02:15,390 so Int.random. And we've already talked about this in detail in previous modules. All that we need 24 25 00:02:15,390 --> 00:02:20,160 to do is provide a range for our random number generator. 25 26 00:02:20,700 --> 00:02:26,880 So, if we want it between 1 and 6, we would write 1... three dots. and then 6. 26 27 00:02:27,090 --> 00:02:35,360 And now this right-hand side is going to generate a random integer between 1 and 6. 27 28 00:02:35,370 --> 00:02:43,710 So, now notice how as soon as I do that, I get an error from Xcode saying that "self" is immutable. 28 29 00:02:43,770 --> 00:02:51,630 And, of course, we remember from our lesson on struct that structures that we create in Swift are immutable. 29 30 00:02:51,630 --> 00:02:57,300 So it means that whenever we need to change any property, the old copy has to be destroyed 30 31 00:02:57,330 --> 00:02:59,940 and the new copy has to replace it. 31 32 00:03:00,150 --> 00:03:08,220 But in the SwiftUI, we have a special property wrapper which we can use called State. 32 33 00:03:08,250 --> 00:03:16,740 So this is going to allow us to update this variable and to get Swift to recreate this ContentView 33 34 00:03:17,130 --> 00:03:21,600 whenever the value of this variable changes or updates. 34 35 00:03:21,600 --> 00:03:28,950 So now if we go ahead and hit command B to build and effectively refresh our errors, you can see that 35 36 00:03:28,950 --> 00:03:34,830 the old error has gone away and we've now got a new error, and it's telling us that we're trying to set 36 37 00:03:34,920 --> 00:03:40,080 a property inside a closure. And when inside a closure, 37 38 00:03:40,080 --> 00:03:46,740 remember we say that we have to add the "self" keyword in front of all of our properties and methods to 38 39 00:03:46,740 --> 00:03:53,520 be explicit about where this property or method lives. And in this case, it's, of course, in this current 39 40 00:03:53,610 --> 00:03:54,680 struct, 40 41 00:03:54,690 --> 00:04:01,990 so that's why we add the "self" in front. So, now let me go ahead and do the same thing for 41 42 00:04:02,000 --> 00:04:09,750 our rightDiceNumber, also gonna set it equal to an integer which is going to be random, and it's going to be between 42 43 00:04:09,810 --> 00:04:17,890 1 and 6 as well. And, of course, we have to mark the rightDiceNumber property with this @State property 43 44 00:04:17,890 --> 00:04:24,460 wrapper as well. That way SwiftUI will also keep track of this rightDiceNumber and rebuild the 44 45 00:04:24,460 --> 00:04:27,100 structure when it changes. 45 46 00:04:27,100 --> 00:04:29,680 So, now let's go ahead and run our app. 46 47 00:04:32,620 --> 00:04:41,170 And now if you click on the Roll button, you should see that both image views will update to randomly 47 48 00:04:41,170 --> 00:04:45,000 show a number between 1 and 6. 48 49 00:04:45,040 --> 00:04:51,250 And this is all possible because we're creating new random numbers and we're updating our properties. 49 50 00:04:51,400 --> 00:04:54,080 Thanks to the @State Property wrapper. 50 51 00:04:54,360 --> 00:04:59,710 SwiftUI knows that it needs to track leftDiceNumber and rightDiceNumber, 51 52 00:04:59,770 --> 00:05:05,710 then when the number changes, SwiftUI will rebuild the entire ContentView, so that we can see the 52 53 00:05:05,710 --> 00:05:08,220 change on screen. 53 54 00:05:08,570 --> 00:05:13,970 This is a good segue way to talk about how SwiftUI works behind the scenes and manages the state 54 55 00:05:14,030 --> 00:05:17,980 of our app. When we've talked about structs in previous modules, 55 56 00:05:17,990 --> 00:05:24,290 we've seen that we can use the "mutating" keyword to mark the functions that are capable of changing a 56 57 00:05:24,290 --> 00:05:27,300 property in our struct. In SwiftUI, 57 58 00:05:27,320 --> 00:05:33,230 we have to do something similar to the struct properties. We have to use a property wrapper, 58 59 00:05:33,230 --> 00:05:35,020 so this @State 59 60 00:05:35,030 --> 00:05:38,180 to mark properties in our struct that can change. 60 61 00:05:38,240 --> 00:05:40,150 Why do we have to do this though? 61 62 00:05:40,190 --> 00:05:46,190 Well, the answer is that it has to do with how SwiftUI works under the hood. While the Secret Service 62 63 00:05:46,190 --> 00:05:53,690 or Santa keeps a list of who has been naughty and who has been nice, SwiftUI keeps a list of who can 63 64 00:05:53,690 --> 00:05:54,740 change. 64 65 00:05:55,100 --> 00:06:02,030 Every time we mark a property with @State, that property goes on a list, and SwiftUI will monitor that 65 66 00:06:02,030 --> 00:06:10,050 list. And by monitored, I mean SwiftUI will know every time something reads or writes to this property. 66 67 00:06:10,100 --> 00:06:14,800 Therefore, SwiftUI knows which views on the screen are using this property. 67 68 00:06:14,840 --> 00:06:23,000 So if that property changes, SwiftUI knows which views on the screen it also needs to update. 68 69 00:06:23,000 --> 00:06:29,450 Let's talk about this in the context of our code. Inside our container view, leftDiceNumber has been 69 70 00:06:29,450 --> 00:06:31,460 marked with @State, 70 71 00:06:31,460 --> 00:06:37,830 so the system knows that our DiceView struct depends on the value of leftDiceNumber. 71 72 00:06:37,850 --> 00:06:40,720 When we push the Roll button, the state changes. 72 73 00:06:41,120 --> 00:06:46,550 SwiftUI will look at the body of the ContentView and it will recalculate everything. 73 74 00:06:46,550 --> 00:06:54,270 Therefore, SwiftUI will now create a new DiceView from scratch representing those changes. And that's 74 75 00:06:54,270 --> 00:06:54,530 it. 75 76 00:06:54,540 --> 00:07:03,660 We've now built an app that not only has appearance and layout, but also has a functionality, all using 76 77 00:07:03,720 --> 00:07:05,190 SwiftUI. 77 78 00:07:05,310 --> 00:07:12,030 So if any part of this lesson was confusing, I recommend having a review of the lessons where we looked 78 79 00:07:12,030 --> 00:07:16,430 at structures and the immutability of structures. 79 80 00:07:16,440 --> 00:07:19,690 So have a search for that if you need a quick review. 80 81 00:07:20,040 --> 00:07:26,940 But in the next lesson, we're going to be building out our app even further to use more advanced ways 81 82 00:07:27,030 --> 00:07:28,690 of managing state. 82 83 00:07:28,780 --> 00:07:31,230 So for all of that and more, I'll see you there.