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.
