0
1
00:00:00,590 --> 00:00:01,070
Hey, guys.
1

2
00:00:01,130 --> 00:00:05,230
Welcome to another lesson on SwiftUI. In this module,
2

3
00:00:05,270 --> 00:00:10,400
We're going to be creating the Dicee app. And in the process, we're going to look at how you can create
3

4
00:00:10,400 --> 00:00:14,280
an app with functionality using SwiftUI.
4

5
00:00:14,300 --> 00:00:20,420
In addition, we're going to get more practice creating layouts using SwiftUI, as well as by working with
5

6
00:00:20,420 --> 00:00:25,640
spaces and padding, as well as creating Subviews with properties that can change.
6

7
00:00:26,540 --> 00:00:33,170
But the most important takeaway from these lessons are going to be how to use SwiftUI to manage the
7

8
00:00:33,170 --> 00:00:34,430
state of the app.
8

9
00:00:35,740 --> 00:00:42,670
In this lesson, we're going to be building out an app that not only has an appearance but it also has
9

10
00:00:42,670 --> 00:00:43,980
functionality.
10

11
00:00:44,020 --> 00:00:49,690
So in this case, the user is actually able to interact with a button on the screen which will be able
11

12
00:00:49,690 --> 00:00:54,010
to change the dice faces in this dice shaker app.
12

13
00:00:54,280 --> 00:00:58,410
Let's get started by creating a brand-new project.
13

14
00:00:58,690 --> 00:01:06,910
And I'm, again, going to choose an iOS Single View App and I'm going to call it Dicer-SwiftUI.
14

15
00:01:06,940 --> 00:01:12,970
Again, make sure that you've got SwiftUI selected as the user interface, and then go ahead and hit Next.
15

16
00:01:14,740 --> 00:01:22,490
Now, save it wherever you like, and then click Create. So the first thing I want you to do is to go ahead
16

17
00:01:22,550 --> 00:01:25,830
and add some image assets to your project.
17

18
00:01:25,910 --> 00:01:33,440
So if you head over to the course resources page, you can find that the Dicee Assets for download under
18

19
00:01:33,500 --> 00:01:37,630
the SwiftUI Module, and then go ahead and download those assets.
19

20
00:01:39,590 --> 00:01:46,580
Once you've got the assets downloaded, unzip the compressed file, and you should find a folder called
20

21
00:01:46,580 --> 00:01:48,770
a Dicee Image Assets.
21

22
00:01:48,770 --> 00:01:54,890
Now, inside here are a bunch of app icons as well as other images that we're going to be using in the
22

23
00:01:54,890 --> 00:01:55,910
app.
23

24
00:01:55,910 --> 00:02:00,770
So I want you to head back over to Xcode in your Assets.xcassets,
24

25
00:02:00,800 --> 00:02:05,450
select the AppIcon placeholder, and click the minus button to delete it.
25

26
00:02:06,080 --> 00:02:11,810
Now, we're going to select all of these app icon sets and image sets, and then just drag it into this
26

27
00:02:11,900 --> 00:02:13,130
section here.
27

28
00:02:13,310 --> 00:02:17,980
And that should add all of the images that we need for this project.
28

29
00:02:17,990 --> 00:02:24,730
So, now we can head back to our ContentView and collapse our left-hand pane.
29

30
00:02:25,010 --> 00:02:29,830
So let's set up the user interface first. In this dice app,
30

31
00:02:29,870 --> 00:02:34,730
I want to give it a background image instead of a background color.
31

32
00:02:34,730 --> 00:02:40,360
So we're going to be using the image set that's called Background that's already in the Assets folder.
32

33
00:02:40,790 --> 00:02:47,120
But go ahead and set up a ZStack with a background image setup.
33

34
00:02:47,300 --> 00:02:51,310
Try and replicate the look that you see here on the right.
34

35
00:02:51,320 --> 00:02:55,060
Pause the video and see if you can complete this challenge.
35

36
00:02:58,540 --> 00:02:58,870
All right.
36

37
00:02:58,900 --> 00:03:06,580
So we can grab a ZStack from our Object library and it's going to be under the first tab, and then I'm
37

38
00:03:06,580 --> 00:03:13,960
just going to drag it into my code. And inside the ZStack, instead of a piece of text, I want to have
38

39
00:03:14,350 --> 00:03:15,410
an image.
39

40
00:03:15,520 --> 00:03:21,480
So I'm going to drag this image view into the stack. And the name of my image,
40

41
00:03:21,500 --> 00:03:25,730
we can just quickly check, it's called background.
41

42
00:03:25,850 --> 00:03:33,040
So let's go back to ContenView and let's change the image name to the string background.
42

43
00:03:33,040 --> 00:03:36,520
So, now once our updates load,
43

44
00:03:39,250 --> 00:03:44,250
you should see that our image background has been placed onto our screen.
44

45
00:03:44,350 --> 00:03:51,190
But the problem is that it's placed in its original aspect ratio which is kind of a square sort of
45

46
00:03:51,190 --> 00:03:52,640
one to one aspect ratio.
46

47
00:03:53,380 --> 00:03:59,140
So in this case, what we need is to make our image resizable.
47

48
00:03:59,260 --> 00:04:04,900
So let's add the resizable modifier, so they can actually change its size.
48

49
00:04:08,620 --> 00:04:15,400
And in addition to making every sizable which makes it take up as much space as it's allowed to,
49

50
00:04:15,490 --> 00:04:19,800
then we're also going to add the ignoring the safe areas,
50

51
00:04:19,840 --> 00:04:22,690
so that was called edgesIgnoringSafeArea.
51

52
00:04:22,840 --> 00:04:27,100
So let's add that as well and make sure that all is applied.
52

53
00:04:27,100 --> 00:04:34,780
So it goes to all four corners ignoring all of the safe areas. And that's the solution to the challenge.
53

54
00:04:34,780 --> 00:04:37,690
Now, let's add the remaining images.
54

55
00:04:37,690 --> 00:04:41,560
So on top of the ZStack, I'm going to create another image view.
55

56
00:04:42,130 --> 00:04:50,310
And in this case, the image view is going to hold the Dicee logo image that came with the assets.
56

57
00:04:50,380 --> 00:04:59,190
So I'm going to create another image and the image was simply called diceeLogo. And there it is.
57

58
00:04:59,190 --> 00:05:03,690
So, now the next objects are not going to go in the Z-axis.
58

59
00:05:03,690 --> 00:05:06,500
It's not going to be on top of the dice logo.
59

60
00:05:06,540 --> 00:05:10,710
In fact, what I need is everything in a vertical stack.
60

61
00:05:11,160 --> 00:05:19,090
So I'm going to hold down my command key and I'm going to drop this diceeLogo into a VStack.
61

62
00:05:19,110 --> 00:05:25,620
Now, in addition to the diceeLogo, I also want to put some of these dice images onto the screen. So I'm
62

63
00:05:25,620 --> 00:05:32,010
going to try and take this dice one image and place it just below my other image.
63

64
00:05:32,010 --> 00:05:34,990
Again, it's going to be using an image component.
64

65
00:05:35,100 --> 00:05:38,040
And in this case, the name was called a dice1.
65

66
00:05:38,640 --> 00:05:47,290
So, now in my preview updates, you should be able to see the logo and the dice face.
66

67
00:05:47,350 --> 00:05:54,340
Now, I'm going to go ahead and resize my dice face. So I'm going to do the same thing as I had up here,
67

68
00:05:54,760 --> 00:06:01,960
so I can either write .resizable. But, of course, following these SwiftUI conventions, it should be
68

69
00:06:02,320 --> 00:06:05,890
lower down so that we can stack each of them together.
69

70
00:06:05,950 --> 00:06:09,960
I'm going to get rid of some of these extra spaces now.
70

71
00:06:09,990 --> 00:06:14,350
Notice how that dice has been stretched beyond recognition.
71

72
00:06:14,370 --> 00:06:21,660
So we're going to change its aspect ratio to make sure that it's always set to an aspect ratio of one
72

73
00:06:21,720 --> 00:06:27,290
which means that it will be one to one on both the vertical and the horizontal.
73

74
00:06:27,510 --> 00:06:33,930
And then I'm going to set the content mode to fit, so that the image actually fitted to the size rather
74

75
00:06:33,930 --> 00:06:42,830
than stretched in an awkward way. Now, because I'm going to need two of these dice faces on the screen,
75

76
00:06:43,280 --> 00:06:47,130
instead of creating another one entirely from scratch,
76

77
00:06:47,150 --> 00:06:54,440
I'm actually going to hold down my commands here and extract this Subview. And I'm going to call my
77

78
00:06:54,440 --> 00:07:05,990
extracted view the DiceView and I'm going to move it just above the content view. And then I'm gonna
78

79
00:07:06,020 --> 00:07:13,670
go ahead and change this number to a dynamic number because we have six dice, and depending on what number
79

80
00:07:13,670 --> 00:07:23,470
I put at the end, I'll end up with a different dice face on screen. So instead of having a hardcode
80

81
00:07:23,470 --> 00:07:27,570
number, I'm going to put a value "n" in there.
81

82
00:07:27,730 --> 00:07:36,720
And when this DiceView struct gets initialized, I'm going to initialize it with the "n" as Int. So, now
82

83
00:07:36,750 --> 00:07:44,940
for this DiceView and it's going to be equal to one, and then I'm gonna drop this DiceView into a horizontal
83

84
00:07:44,940 --> 00:07:51,850
stack and copy it so that I have two of them.
84

85
00:07:51,980 --> 00:07:53,810
So there we go.
85

86
00:07:53,810 --> 00:08:00,590
Now, notice how at the moment, they're going all the way to the edges which is a little bit too much.
86

87
00:08:00,680 --> 00:08:08,000
So I want to add some padding to my HStack. So right at the end of the closing brace for the HStack,
87

88
00:08:08,060 --> 00:08:17,800
I'm gonna hit enter and I'm going to add my padding by writing .padding. And if I go ahead and just
88

89
00:08:17,920 --> 00:08:22,900
add this padding as it is, it will get added to all four sides.
89

90
00:08:23,110 --> 00:08:30,130
But if you only want it on a particular side, then inside the parentheses, you can specify which edge
90

91
00:08:30,160 --> 00:08:31,790
you want to add the padding to.
91

92
00:08:32,230 --> 00:08:37,220
And in my case, I want to keep it just on the horizontal sides.
92

93
00:08:37,270 --> 00:08:44,070
Now, the last element I'm going to add into my user interface is going to be a button.
93

94
00:08:44,170 --> 00:08:50,360
So let's search for a button and just go ahead and drag it into your code.
94

95
00:08:50,380 --> 00:08:55,650
I find that when you actually drag it onto the screen, it has so many options to choose from.
95

96
00:08:55,660 --> 00:08:59,170
You often get it ending up somewhere where you don't want it to be.
96

97
00:08:59,230 --> 00:09:07,120
So I want it inside this VStack alongside my diceeLogo, my DiceViews and my Button.
97

98
00:09:07,120 --> 00:09:15,130
So in this case, the button is going to say "Roll" and the action is going to be determined by what's inside
98

99
00:09:15,190 --> 00:09:17,080
these set of curly braces.
99

100
00:09:17,080 --> 00:09:23,880
So let's hit enter and activate that closure. And let's first modify our Text.
100

101
00:09:24,130 --> 00:09:26,730
So at the moment, it's really, really small.
101

102
00:09:26,800 --> 00:09:37,060
So I want to go ahead and change the font to a system font and I'm going to specify a size. So the size
102

103
00:09:37,060 --> 00:09:40,840
is going to be a 50.font to make it really large.
103

104
00:09:41,170 --> 00:09:46,300
And then I'm going to change the fontWeight to a heavy set font,
104

105
00:09:46,300 --> 00:09:49,720
so just a bit thicker than bold.
105

106
00:09:49,720 --> 00:09:55,900
And finally, I'm going to change the foreground color which is going to be the text color effectively
106

107
00:09:56,500 --> 00:10:01,630
and that's going to be white. And the button itself,
107

108
00:10:01,690 --> 00:10:04,840
so outside of these curly braces,
108

109
00:10:04,840 --> 00:10:15,940
so not in the text area. But down here, we can set the background color of the button to Color.red
109

110
00:10:16,300 --> 00:10:20,120
to make it a red background.
110

111
00:10:20,170 --> 00:10:26,980
And finally, if we want our text to have a little bit of padding before it reaches the edges of the button,
111

112
00:10:27,430 --> 00:10:33,010
we can go ahead and add some padding right here.
112

113
00:10:33,120 --> 00:10:41,020
And, again, if you only want it along the horizontal, then we can use the .horizontal modifier.
113

114
00:10:41,120 --> 00:10:41,450
All right.
114

115
00:10:41,480 --> 00:10:46,740
So now it's looking pretty close to our end results.
115

116
00:10:46,760 --> 00:10:53,720
The only thing that I would, perhaps, change is to just give the image a little bit of padding around
116

117
00:10:53,840 --> 00:10:57,550
four edges, so that they separate out from each other a little bit.
117

118
00:10:57,650 --> 00:10:59,230
So it's easier to see.
118

119
00:10:59,510 --> 00:11:07,760
So in the extracted Subview, our DiceView, I'm going to change the image modifier to add some padding
119

120
00:11:07,850 --> 00:11:13,340
around all four sides. And then let's go ahead and reindent our code.
120

121
00:11:13,350 --> 00:11:16,130
And now that's looking a lot better.
121

122
00:11:16,190 --> 00:11:20,440
So in previous lessons, this is how we've seen all these stacks.
122

123
00:11:20,450 --> 00:11:24,790
Everything is stacked together with a little bit of gap in between each element.
123

124
00:11:25,310 --> 00:11:34,220
But what if we wanted to be able to push the stack to take up the full width or length that it has access
124

125
00:11:34,220 --> 00:11:34,550
to?
125

126
00:11:35,070 --> 00:11:41,510
Well, in this case, we could, for example, add some separation between our dice logo and our HStack.
126

127
00:11:41,660 --> 00:11:49,760
So we would do that using something called a spacer. So a spacer is going to create a flexible amount
127

128
00:11:49,760 --> 00:11:53,590
of space depending on how much space there is on the screen.
128

129
00:11:53,630 --> 00:12:00,440
So if it's a small aspect ratio phone or if it's in landscape, then it would shrink that space down automatically
129

130
00:12:00,920 --> 00:12:05,390
without us having to create any constraints or any order layout rules.
130

131
00:12:05,960 --> 00:12:13,520
So let's go ahead and drag our Spacer in between our image and our HStack which will now push these
131

132
00:12:13,520 --> 00:12:19,610
two away, and the spacer will try to take up as much space as it possibly has access to.
132

133
00:12:19,670 --> 00:12:26,330
Now, in addition to having a space between the logo and the dice, I'm also gonna put a spacer between
133

134
00:12:26,330 --> 00:12:33,590
the dice and my Button, so that everything is pretty much evenly distributed on the screen.
134

135
00:12:33,590 --> 00:12:34,100
That's it.
135

136
00:12:34,100 --> 00:12:38,230
That's all we had to do to set up the user interface.
136

137
00:12:38,280 --> 00:12:42,770
There's nothing really new in the code here that you haven't seen before
137

138
00:12:42,980 --> 00:12:49,610
other than, perhaps, the spacer which is a really flexible component that helps us layout our user interface
138

139
00:12:49,610 --> 00:12:51,980
for different sized screens.
139

140
00:12:52,100 --> 00:12:57,440
So, now all you need to do is figure out how do we change the dice 
140

141
00:12:57,440 --> 00:13:03,480
images. And that's exactly what we're going to be covering in the next video where we're going to learn
141

142
00:13:03,540 --> 00:13:06,090
about managing state in the SwiftUI.
