0
1
00:00:00,580 --> 00:00:08,410
So up till now, we've created a brand-new TableViewController that's embedded inside a navigation 
1

2
00:00:08,410 --> 00:00:08,650
controller.
2

3
00:00:09,160 --> 00:00:12,580
So we have this top bar here for our Todoey app.
3

4
00:00:12,580 --> 00:00:20,170
We've added items that have been hardcoded and we're able to now select them and add a checkmark, or
4

5
00:00:20,170 --> 00:00:23,310
deselect them and remove the checkmark.
5

6
00:00:23,320 --> 00:00:28,930
Now, let's go back to our TodoListViewController and add some more functionality.
6

7
00:00:28,930 --> 00:00:37,150
We wanted to be able to have a button on our app that allows us to add new items to our to-do list.
7

8
00:00:37,240 --> 00:00:45,290
So the easiest way of achieving this is by adding a bar button item to our TodoListViewController.
8

9
00:00:45,310 --> 00:00:53,920
So if we go ahead and search for a bar button item and we can drag it up to the top right here of our
9

10
00:00:53,920 --> 00:01:01,590
top bar, and I'm going to change the system item to add to get this nice little plus sign,
10

11
00:01:01,930 --> 00:01:09,030
and I'm also going to change the tint to white so that it matches my current palette.
11

12
00:01:09,190 --> 00:01:16,180
So, now that I've got that going on, I'm going to link this into my file as an IBAction.
12

13
00:01:16,180 --> 00:01:21,620
So I'm going to scroll down all the way to the bottom, I'm going to make a new pragma MARK,
13

14
00:01:22,000 --> 00:01:30,670
and this is going to be the "Add New Items" section. And then I'm going to create my IBAction right here,
14

15
00:01:30,670 --> 00:01:38,860
I'm going to change from outlet to action, and let's call it addButtonPressed,
15

16
00:01:38,860 --> 00:01:47,200
change it from any to more specific UI button BarButtonItem, and hit Connect.
16

17
00:01:47,420 --> 00:01:54,110
So, now I've got this brand new IBAction where I can add code to determine what should happen when the
17

18
00:01:54,110 --> 00:02:03,620
user presses that addButton. Here, what I want to happen is for a pop-up or a UIAlertController to
18

19
00:02:03,620 --> 00:02:11,990
show when I press the addButton and to have a text field in that UIAlert, so that I can write a quick
19

20
00:02:11,990 --> 00:02:18,560
to-do list item, and then append it to the end of my itemArray.
20

21
00:02:18,560 --> 00:02:26,160
So let's create a brand-new alert, so let alert = UIAlertController,
21

22
00:02:26,480 --> 00:02:31,300
and it's going to be the one with title message and preferred style.
22

23
00:02:31,370 --> 00:02:38,930
So the title will be something like "Add New Todoey Item," and the message,
23

24
00:02:38,930 --> 00:02:46,420
I'm actually going to leave blank, and the preferredStyle is just going to be alert, the default style.
24

25
00:02:46,820 --> 00:02:49,620
And then I'm gonna create an action,
25

26
00:02:49,790 --> 00:02:58,040
so this is gonna be a UIAlertAction and this action is going to have a title, a style, and a handler.
26

27
00:02:58,760 --> 00:03:02,900
So the title will be "Add Item."
27

28
00:03:02,900 --> 00:03:07,820
So this is gonna be the button that you're gonna press once you're done with writing your new to-do
28

29
00:03:07,820 --> 00:03:08,940
list item.
29

30
00:03:09,050 --> 00:03:13,660
The style is going to be default. And the handler,
30

31
00:03:13,670 --> 00:03:17,620
I'm just going to select this placeholder, so make it blue,
31

32
00:03:17,630 --> 00:03:26,720
I'm gonna hit enter to create a completion handler or a closure. So the action, I'm going to name action.
32

33
00:03:27,190 --> 00:03:30,590
I'm gonna delete the code placeholder.
33

34
00:03:30,590 --> 00:03:44,560
And here is gonna be "what will happen once the user clicks the Add Item button on our UIAlert."
34

35
00:03:44,570 --> 00:03:50,750
So, now let's add the action to our alert, addAction,
35

36
00:03:50,750 --> 00:03:53,390
the action is called action.
36

37
00:03:53,390 --> 00:03:55,040
Now, this is all very well and good,
37

38
00:03:55,070 --> 00:04:00,910
and we can check to make sure that it works by saying print "Success."
38

39
00:04:01,670 --> 00:04:04,820
And finally, we need to show our alert.
39

40
00:04:05,090 --> 00:04:12,170
So we're simply going to say present, and it's a viewController that we want to present, and the
40

41
00:04:12,190 --> 00:04:19,880
viewController to present, and the viewController is, of course, our alertViewController, animated: true, and completion:
41

42
00:04:19,940 --> 00:04:21,550
nil.
42

43
00:04:21,560 --> 00:04:24,880
Now, let's hit run and see what we've got so far.
43

44
00:04:25,070 --> 00:04:29,870
So we've got this brand-new add button as a bar button item
44

45
00:04:29,870 --> 00:04:34,970
and when we click on it, we activate this IBAction and we've created this brand-new alert.
45

46
00:04:35,990 --> 00:04:43,640
So, now when we click add item, all we get is just success printed to the debug console and nothing else.
46

47
00:04:43,640 --> 00:04:51,410
Now, what I want to happen next is, instead of just having a simple UI alert, I want to include a text
47

48
00:04:51,410 --> 00:04:58,880
field in this alert so that I can get the user to write a new to-do list item, and then when I click
48

49
00:04:58,940 --> 00:05:05,960
an item, I'm going to print what they wrote into the debug console here. In order to add a text field
49

50
00:05:06,050 --> 00:05:07,560
to our alert,
50

51
00:05:07,580 --> 00:05:15,650
it's very similar to adding an action, but all we have to do is say, alert.addTextField, and in the
51

52
00:05:15,650 --> 00:05:22,580
completion handler, we're going to select this placeholder and make it blue, and then hit enter to insert
52

53
00:05:22,850 --> 00:05:24,350
that closure.
53

54
00:05:24,350 --> 00:05:32,460
We're going to call the text field that we create alertTextField. And in the completion block, we're
54

55
00:05:32,460 --> 00:05:35,490
going to set up the alertTextFields.
55

56
00:05:35,490 --> 00:05:38,850
We're going to say alertTextField.placeholder.
56

57
00:05:38,970 --> 00:05:44,250
So this is the string that's going to show in gray and it's going to disappear when the user clicks
57

58
00:05:44,250 --> 00:05:45,320
on that text field.
58

59
00:05:45,420 --> 00:05:53,280
So a placeholder is going to say something like "Create new item," and then we're going to print whatever
59

60
00:05:53,280 --> 00:05:57,250
text is inside the alertTextField, so alertTextField.text.
60

61
00:05:57,660 --> 00:06:01,360
So let's go ahead and run this and see what happens.
61

62
00:06:02,760 --> 00:06:04,760
So let's click the Add button.
62

63
00:06:04,950 --> 00:06:11,550
You can see now we have a UIAlert that has a title, a new text field, and also a button.
63

64
00:06:11,550 --> 00:06:15,000
So it's got that placeholder there where it says, "Create new item."
64

65
00:06:15,060 --> 00:06:19,020
And as soon as we start typing, that placeholder is going to disappear.
65

66
00:06:19,020 --> 00:06:28,450
So let's say our new item is "Save the world!" and if I click add item, that disappears.
66

67
00:06:28,540 --> 00:06:34,930
And the problem that we have is that the point at which we click that button, we can write some code
67

68
00:06:35,440 --> 00:06:38,800
that specifies what should happen
68

69
00:06:39,010 --> 00:06:47,350
once the user clicks the add Item button on our alert. But the alertTextField is created as a local
69

70
00:06:47,350 --> 00:06:50,600
variable only inside this closure.
70

71
00:06:50,620 --> 00:06:56,590
So how do I grab what exists in here and print it
71

72
00:06:56,590 --> 00:07:00,550
once the user presses the ad Item button?
72

73
00:07:00,580 --> 00:07:02,610
So this is a bit of a tricky question.
73

74
00:07:02,650 --> 00:07:07,380
And you can have a think about it and see if you can figure it out,
74

75
00:07:07,420 --> 00:07:13,210
then this is a good time point to pause the video. But if you want to follow along with me, then I'm going
75

76
00:07:13,210 --> 00:07:15,630
to show you the solution.
76

77
00:07:15,640 --> 00:07:21,910
So, essentially, what we need is a local variable inside this IBAction.
77

78
00:07:21,910 --> 00:07:30,100
So inside the scope between these two curly braces that's accessible to all of these other completion
78

79
00:07:30,100 --> 00:07:30,970
handlers.
79

80
00:07:30,970 --> 00:07:38,140
So currently, I've got this alertTextField that has the scope of just this closure. And if I want to
80

81
00:07:38,140 --> 00:07:45,580
change it's very, very limited scope, i.e., being available just inside here, then I have to create a local
81

82
00:07:45,580 --> 00:07:54,210
variable within the scope of this addButtonPressed, so anywhere that's outside of one of these closures.
82

83
00:07:54,220 --> 00:08:02,620
So what we can do is we can create a textField up here which is going to be a UITextField and we're
83

84
00:08:02,620 --> 00:08:05,470
going to initialize it to an empty UITextField.
84

85
00:08:05,470 --> 00:08:13,480
Now, this text field has the scope of the entire addButtonPressed IBAction and is going to be
85

86
00:08:13,480 --> 00:08:17,490
accessible inside here as well as inside here.
86

87
00:08:17,530 --> 00:08:24,970
Now, at this stage, what we can do is we can set this text field with a wider scope to equal
87

88
00:08:24,970 --> 00:08:31,540
the alertTextField that has a slightly narrower scope because it's only available inside here.
88

89
00:08:31,540 --> 00:08:35,860
So if you write alertTextField, you can see the autosuggests come up here,
89

90
00:08:35,860 --> 00:08:43,150
but if you tried it outside the closure, alertTextField, nothing happens because it doesn't exist outside
90

91
00:08:43,330 --> 00:08:44,800
the scope of this closure.
91

92
00:08:45,280 --> 00:08:52,440
So we're extending the scope of that alertTextField to this addButtonPressed.
92

93
00:08:52,480 --> 00:08:56,600
Now, the sequence of events matters a great deal.
93

94
00:08:56,650 --> 00:09:03,310
You might think that you can simply write print(alertTextField.text)
94

95
00:09:03,380 --> 00:09:09,890
but the reason why this is not going to print you what the users typed into that text field is because
95

96
00:09:09,890 --> 00:09:16,970
this closure only gets triggered once the text field has been added to the alert.
96

97
00:09:16,970 --> 00:09:20,000
So it's at this time point when it happens.
97

98
00:09:20,420 --> 00:09:28,370
And what we can do is we can print something to our debug console to see when this closure gets triggered.
98

99
00:09:28,430 --> 00:09:34,580
So if I hit run, and let's just move that over here and make our debug console a little bit bigger,
99

100
00:09:34,580 --> 00:09:44,840
now I'm gonna click add, and you can see that this line here where it says, "optional empty string," refers
100

101
00:09:44,840 --> 00:09:46,550
to this print statement.
101

102
00:09:46,550 --> 00:09:52,580
It's trying to print the text that's currently inside the alertTextField which is, of course, empty.
102

103
00:09:53,270 --> 00:10:01,160
And we get the "Now" printed at the point when are text field is added to the alert,
103

104
00:10:01,190 --> 00:10:03,090
so when it shows up here.
104

105
00:10:03,380 --> 00:10:10,700
But when we type something in here and we click add item, nothing happens, there's no print statement that
105

106
00:10:10,700 --> 00:10:17,840
happens, because that time point is covered by this completion block when the user clicks the add Item
106

107
00:10:17,840 --> 00:10:18,910
button.
107

108
00:10:18,920 --> 00:10:25,490
This is the place that we're going to get something happening and we can show that by just using a
108

109
00:10:29,000 --> 00:10:30,760
print statement here.
109

110
00:10:30,980 --> 00:10:36,320
So you can see that as soon as I press the add button, that's when the "Now" gets printed.
110

111
00:10:36,320 --> 00:10:44,000
But when I click the add item, that's the point where we get the add item pressed printed because this
111

112
00:10:44,000 --> 00:10:52,190
is the completion blog that gets called once that add Item button gets pressed. So we can solve that timing
112

113
00:10:52,190 --> 00:11:01,820
problem by simply storing a reference to that alertTextField inside a local variable that's available
113

114
00:11:01,910 --> 00:11:05,330
to everybody inside the addButtonPressed.
114

115
00:11:05,510 --> 00:11:09,290
And this text field is what we're going to print inside here.
115

116
00:11:09,320 --> 00:11:18,170
So we're going to say print(textField.text) instead of this print statement. And I'm going to delete
116

117
00:11:18,200 --> 00:11:22,700
that print "Now" as well, and I'm going to hit run.
117

118
00:11:22,700 --> 00:11:28,290
So, now when I pressed the Add button, I don't get anything printed in here,
118

119
00:11:28,490 --> 00:11:38,690
othe than not very useful messages from Xcode. But if I now write something in here and I click the Add Item button,
119

120
00:11:39,560 --> 00:11:46,300
I get whatever I typed into that text field, print it out here because of this print statement.
120

121
00:11:47,660 --> 00:11:54,650
If that seemed confusing, it might be a good point to review the lessons on scope that we covered earlier
121

122
00:11:54,650 --> 00:11:55,710
on.
122

123
00:11:55,850 --> 00:12:04,760
Now, it's really important that you understand where these local variables are available and how you
123

124
00:12:04,760 --> 00:12:08,990
can use them to store data and read data.
124

125
00:12:09,590 --> 00:12:17,390
So instead of this print statement, what we actually want to happen is we want to add whatever text the
125

126
00:12:17,390 --> 00:12:24,190
user created to our itemArray and append it into this array at the end.
126

127
00:12:24,200 --> 00:12:33,050
Now, before we can append an item to our itemArray, we first have to change this array from being immutable
127

128
00:12:33,350 --> 00:12:40,730
because it's a constant to mutable by getting rid of that "let" and changing it to a "var."
128

129
00:12:40,760 --> 00:12:48,590
So, now what we can do is we can say itemArray.append, and the new element that we want to append
129

130
00:12:48,890 --> 00:12:57,230
has to be a string and it's going to be textField.text and we're going to force unwrap that because
130

131
00:12:57,290 --> 00:13:03,770
the text property of a text field is never going to equal nil, even if it's empty, it's going to be set
131

132
00:13:03,830 --> 00:13:05,210
to an empty string.
132

133
00:13:05,210 --> 00:13:10,270
Now, you can add some more checking code in here to maybe prevent the action from going forwards
133

134
00:13:10,430 --> 00:13:14,210
if the text field was empty or add some more validation code.
134

135
00:13:14,510 --> 00:13:21,140
But for now, we're just going to say that if the user entered nothing, it will just simply have an empty
135

136
00:13:21,140 --> 00:13:21,850
cell.
136

137
00:13:21,860 --> 00:13:25,400
Now, it's not ideal and there's quite a few workarounds to this.
137

138
00:13:25,400 --> 00:13:29,560
For example, we can give it a default value if it was nil.
138

139
00:13:29,570 --> 00:13:36,830
So we can say if textfield.text was nil, then simply append the string "New item."
139

140
00:13:36,830 --> 00:13:40,640
Now, that doesn't really look much better than an empty string,
140

141
00:13:40,640 --> 00:13:42,520
so that's not a great solution.
141

142
00:13:42,560 --> 00:13:48,620
A more sophisticated solution would be to prevent the action from going through if the textField.text
142

143
00:13:48,740 --> 00:13:50,030
was empty.
143

144
00:13:50,150 --> 00:13:52,160
But that's going to take a lot more lines of code.
144

145
00:13:52,190 --> 00:13:55,790
And right now, we want to focus on our objective here.
145

146
00:13:55,970 --> 00:14:02,720
So itemArray.append(textField.text!) And because I'm inside a closure, remember, the "in" keyword,
146

147
00:14:03,200 --> 00:14:11,030
I have to specify "self" to tell the compiler explicitly where this itemArray exists, i.e., in the current
147

148
00:14:11,030 --> 00:14:11,640
class.
148

149
00:14:11,660 --> 00:14:20,600
So, now if I run my app, you might expect it to work because we're pending whatever the user adds in
149

150
00:14:20,600 --> 00:14:28,610
the text field to this array and our tableView cellForRowAt indexPath uses this array. But as you'll
150

151
00:14:28,610 --> 00:14:39,600
shortly see, if I click on the add button and I add a new item, and I click Add Item, nothing changes in
151

152
00:14:39,600 --> 00:14:43,620
my table view. Table view hasn't changed one bit,
152

153
00:14:43,710 --> 00:14:52,230
despite the fact that we've added what the user wrote in the text field into our itemArray and our
153

154
00:14:52,230 --> 00:15:01,290
cell's textLabel is created from the itemArray. But if you'll believe me, I can tell you that it's definitely
154

155
00:15:01,290 --> 00:15:07,010
been added to this itemArray. So why is it not showing up in our table view?
155

156
00:15:07,350 --> 00:15:10,720
If you don't want to believe me, that's also perfectly valid.
156

157
00:15:10,770 --> 00:15:14,250
It's always good idea to test and not trust.
157

158
00:15:14,250 --> 00:15:22,620
So what I can do is I can put a breakpoint at this line where we've appended that item, and I can stop
158

159
00:15:22,620 --> 00:15:32,720
the app and run the app again. I'm going to add a new item, and once I hit Add Item
159

160
00:15:32,730 --> 00:15:38,490
same as before, but we now enter our debug session because our breakpoint is triggering it.
160

161
00:15:38,550 --> 00:15:46,530
So at the moment, before this line is carried out, and I print in my debug console the current value of
161

162
00:15:46,590 --> 00:15:49,740
itemArray and I hit enter,
162

163
00:15:49,740 --> 00:15:54,220
you can see that it's only got three items: "Find Mike," "Buy Eggos," "Destroy Demogorgon."
163

164
00:15:54,750 --> 00:16:01,530
Now, if I choose to step over this instruction, so carry it out,
164

165
00:16:01,710 --> 00:16:07,470
now if I hit print itemArray, hit enter,
165

166
00:16:07,590 --> 00:16:14,370
you can see I've now got four items, and that item has been added to my array itemArray.
166

167
00:16:14,610 --> 00:16:16,980
So, now I hope you'll believe me.
167

168
00:16:17,130 --> 00:16:19,410
But what do we do about this?
168

169
00:16:19,410 --> 00:16:26,920
How can we get it to show up in our table view? And the magic method is reload data.
169

170
00:16:27,060 --> 00:16:33,600
And this reloads the rows and the sections of the table view, taking into account the new data that we've
170

171
00:16:33,660 --> 00:16:35,690
added to our itemArray.
171

172
00:16:35,700 --> 00:16:46,850
So, now if I hit run and I add a new item to our to-do list, and I hit add item, then it reloads the text field
172

173
00:16:47,140 --> 00:16:52,030
takeing account the new array, and now it populates my table view.
173

174
00:16:52,040 --> 00:16:55,140
So in this lesson, we looked at a couple of things.
174

175
00:16:55,340 --> 00:16:58,950
We added a new bar button item.
175

176
00:16:58,970 --> 00:17:01,040
We created an IBAction.
176

177
00:17:01,040 --> 00:17:05,240
We created an alert that has an action as well as a text field.
177

178
00:17:05,330 --> 00:17:09,300
And once the user clicks the Add item button in our alert,
178

179
00:17:09,350 --> 00:17:15,380
then we add whatever they wrote in the text field to our itemArray, and then we reload the table view
179

180
00:17:15,410 --> 00:17:17,330
to show that data.
180

181
00:17:17,390 --> 00:17:22,910
So in the next lesson, we're going to be getting on to our main topic: Data
181

182
00:17:22,910 --> 00:17:24,340
Persistence,
182

183
00:17:24,410 --> 00:17:27,180
what can we do to persist the data.
183

184
00:17:27,200 --> 00:17:32,350
I'm going to show you the problem that we currently have that we're not yet aware of, but you're going
184

185
00:17:32,350 --> 00:17:33,470
to see it very soon.
185

186
00:17:33,680 --> 00:17:39,800
And then I'm going to show you one of the easiest ways of persisting data. So all of that and more on
186

187
00:17:39,800 --> 00:17:40,490
the next lesson.
