0
1
00:00:01,030 --> 00:00:08,850
All right, so in the last lesson, we managed to get our swipe cells to work and we can now swipe on our categories
1

2
00:00:09,150 --> 00:00:12,990
to delete them, and then updates our model accordingly.
2

3
00:00:12,990 --> 00:00:19,440
Now, in this lesson, we're going to talk about how we can copy that functionality over to our 
3

4
00:00:19,440 --> 00:00:23,550
TodoListViewController without having to copy all of the code.
4

5
00:00:23,550 --> 00:00:30,000
And we mentioned that the way that we're going to tackle this problem is by creating a superclass where
5

6
00:00:30,060 --> 00:00:32,840
both of these view controllers can inherit from.
6

7
00:00:32,850 --> 00:00:34,110
So let's go ahead and do that.
7

8
00:00:34,140 --> 00:00:35,560
Let's hit command N
8

9
00:00:35,880 --> 00:00:39,150
and we're going to create a new Cocoa Touch Class.
9

10
00:00:39,210 --> 00:00:45,340
And the reason is because we want to inherit from UITableViewController because both of these view controllers
10

11
00:00:45,390 --> 00:00:46,990
are TableViewControllers.
11

12
00:00:47,280 --> 00:00:52,190
And if we need some of that functionality, then we can inherit it over.
12

13
00:00:52,200 --> 00:00:59,070
So we're going to call this class the SwipeTableViewController and we're going to hit Next, and we're
13

14
00:00:59,070 --> 00:01:02,220
going to save it in our group of controllers.
14

15
00:01:02,430 --> 00:01:05,660
And now this is going to be our superclass.
15

16
00:01:05,790 --> 00:01:10,790
And so we need to add all of the swipe cell functionality inside here.
16

17
00:01:10,890 --> 00:01:19,380
So we're going to import SwipeCellKit, of course, and we're going to adopt the protocol which is 
17

18
00:01:19,850 --> 00:01:31,380
SwipeTableViewCellViewCellDelegate, and I'm going to delete all of this stuff that Xcode
18

19
00:01:31,380 --> 00:01:37,740
has automatically put in here so that we have a nice and clean view controller to work with.
19

20
00:01:38,070 --> 00:01:44,720
Okay, so now we need to copy over everything, basically, that's inside our extension.
20

21
00:01:44,870 --> 00:01:53,160
So I'm going to hit Cut and I'm going to paste it over here. Now because this is a separate class that
21

22
00:01:53,250 --> 00:01:56,010
only deals with the swipe cell functionality,
22

23
00:01:56,010 --> 00:02:00,990
it doesn't actually make sense for it to be inside a separate extension because then our main class
23

24
00:02:00,990 --> 00:02:01,730
would be empty,
24

25
00:02:01,740 --> 00:02:02,060
right?
25

26
00:02:02,070 --> 00:02:03,330
That isn't making sense.
26

27
00:02:03,360 --> 00:02:11,670
So we can go ahead and take out our delegate methods from this extension by cutting it and putting it
27

28
00:02:11,850 --> 00:02:19,460
inside our SwipeTableViewController and we can delete our extension completely.
28

29
00:02:19,500 --> 00:02:27,020
So, now we have both of those swipe cell delegate methods inside our SwipeTableViewController.
29

30
00:02:27,330 --> 00:02:34,650
But one thing that we can't do in here is we can't delete our categories because, remember, if we're going
30

31
00:02:34,650 --> 00:02:42,000
to inherit this class inside both of these classes, we can't have any specific code relating to each
31

32
00:02:42,000 --> 00:02:43,230
of these view controllers.
32

33
00:02:43,380 --> 00:02:49,980
So the superclasses are not meant to have any knowledge of their subclasses or their children.
33

34
00:02:50,010 --> 00:02:55,110
So it sounds a bit cruel, but that's just the way it is.
34

35
00:02:55,290 --> 00:02:59,550
If you watch "Planet Earth," you will realize that the world is pretty ambivalent
35

36
00:02:59,580 --> 00:03:08,760
the struggles of individuals. And in the world of coding and Swift, it's also the same. Sadly, our 
36

37
00:03:08,760 --> 00:03:14,550
SwipeTableViewController is going to have all of these children category to view controller and TodoListViewController,
37

38
00:03:14,790 --> 00:03:17,370
but it's not going to care or know about it.
38

39
00:03:17,670 --> 00:03:21,110
So there's a little bit of downer for you, but it will be okay.
39

40
00:03:21,120 --> 00:03:27,930
So I'm going to actually just comment out that block of code, and instead, I'm just going to write print
40

41
00:03:28,350 --> 00:03:34,800
"Delete cell," just so that we know that this is actually being called when we test it later on.
41

42
00:03:34,800 --> 00:03:35,100
All right.
42

43
00:03:35,100 --> 00:03:38,170
So I think that's all that we need to do over here.
43

44
00:03:38,430 --> 00:03:43,860
But let's head back to our CategoryViewController and delete that pragma MARK as well.
44

45
00:03:43,980 --> 00:03:50,970
So, now instead of our CategoryViewController inheriting from UITableViewController, we're actually
45

46
00:03:50,970 --> 00:03:57,180
going to inherit from the SwipeTableViewController. So we can go ahead and delete this and simply
46

47
00:03:57,180 --> 00:04:03,740
write SwipeTableViewController and that was our custom class that we created.
47

48
00:04:03,750 --> 00:04:11,640
So because we want to keep all of these swipe cell functionality inside the superclass 
48

49
00:04:11,640 --> 00:04:12,520
SwipTableViewController,
49

50
00:04:12,720 --> 00:04:19,710
we actually don't really want any sort of mention to SwipeCellKit inside the subclass which is our
50

51
00:04:19,710 --> 00:04:21,190
CategoryViewController.
51

52
00:04:21,240 --> 00:04:27,910
So I want to be able to delete this import statement and to get rid of all of the mentions of
52

53
00:04:27,910 --> 00:04:35,220
SwipeCellKit. And pretty much, as soon as you do that, we get an error here that tells us, "Hey, by the way,
53

54
00:04:35,220 --> 00:04:39,300
you created the cell and you said that it has to be a swipe cell."
54

55
00:04:39,660 --> 00:04:45,480
And also you set the cell's delegate in order to allow the SwipeCellsDelegateMethods to trigger and
55

56
00:04:45,480 --> 00:04:47,500
inform this current class.
56

57
00:04:47,580 --> 00:04:56,160
So we don't want either of these lines of code. But the code that we do need is to change the textLabel
57

58
00:04:56,370 --> 00:05:03,180
based on the categories inside this view. And SwipeTableViewCell cannot know anything about those
58

59
00:05:03,180 --> 00:05:04,180
categories.
59

60
00:05:04,230 --> 00:05:07,380
So how can we square that circle?
60

61
00:05:07,770 --> 00:05:15,090
So what we can do is we can create the superclass table view cellForRowAt indexPath, and then we can
61

62
00:05:15,270 --> 00:05:21,300
override it over here and add a little bit more information to that cell.
62

63
00:05:21,300 --> 00:05:29,940
So let's, first, head over to SwipeTableViewCell and we're going to add some TableView Datasource
63

64
00:05:30,300 --> 00:05:36,970
Methods. And the one that we really do need is the cellForRowAt indexPath.
64

65
00:05:37,230 --> 00:05:40,680
And here is where we want to initialize the SwipeTableViewCell
65

66
00:05:40,680 --> 00:05:45,870
as the default cell for all of the table views that inherit this class.
66

67
00:05:45,990 --> 00:05:52,230
So we can go ahead and copy some of this code over and I'm going to delete this code that we copied
67

68
00:05:52,230 --> 00:05:57,590
over from the Swipe Cell Documentation just to make everything a little bit clearer.
68

69
00:05:57,990 --> 00:06:05,430
So let's head over here and paste that code in here. So you can see that what we did in CategoryViewController
69

70
00:06:05,430 --> 00:06:14,910
is that we created a new cell by dequeuing it using the identifier CategoryCell. Now, we can't have
70

71
00:06:14,910 --> 00:06:16,320
something called CategoryCell
71

72
00:06:16,310 --> 00:06:20,200
if this class doesn't know about it's subclasses, right?
72

73
00:06:20,220 --> 00:06:24,600
So we have to change this name to something more generic like just "Cell."
73

74
00:06:24,900 --> 00:06:32,430
And for that to work, we have to go back into our Main. storyboard and change both the identifier for
74

75
00:06:32,430 --> 00:06:40,410
the CategoryCell to Cell. And, also, because we want both the TodoListViewController and the 
75

76
00:06:40,410 --> 00:06:44,910
CategoryViewController to use swipe cells from the SwipeTableViewController.
76

77
00:06:45,000 --> 00:06:50,110
We're going to rename the ToDoItemCell also to Cell as well.
77

78
00:06:50,130 --> 00:06:52,250
So let's hit save on that
78

79
00:06:52,410 --> 00:06:58,140
and let's go back to SwipeTableVieCell and you're gonna see that our identifier is now Cell and that will work
79

80
00:06:58,170 --> 00:07:01,200
for either of those subclasses.
80

81
00:07:01,200 --> 00:07:08,130
And then we get onto this line and this line basically can't exist because we don't know about categories
81

82
00:07:08,160 --> 00:07:09,780
inside SwipeTableViewController,
82

83
00:07:09,810 --> 00:07:13,310
and we certainly don't know about our data model in here.
83

84
00:07:13,320 --> 00:07:16,060
This is just a front-end UIClass.
84

85
00:07:16,230 --> 00:07:21,870
So we're going to go ahead and delete that and we're going to keep cell.delegate as self because
85

86
00:07:21,930 --> 00:07:26,820
this is the place that has all of those delegate methods that will deal with the deletions.
86

87
00:07:27,120 --> 00:07:33,690
And then we're going to return the cell. And that is all we need to do inside this superclass.
87

88
00:07:33,690 --> 00:07:40,080
Now, we're going to head over to our subclass which is the CategoryViewController and we need to fix
88

89
00:07:40,140 --> 00:07:46,380
some issues here because we need to be able to set the cell's textLabel.ext property to the name
89

90
00:07:46,440 --> 00:07:49,210
of the categories in our Data Model.
90

91
00:07:49,350 --> 00:07:54,910
But if we're not going to initialize the cell here, then how can we tap into it?
91

92
00:07:55,140 --> 00:08:01,740
So let's go ahead and delete all the bits of code that we've put in the superclass and we can tap into
92

93
00:08:01,740 --> 00:08:11,400
that superclass by saying let cell = super.tableView and the tableView is the same as the
93

94
00:08:11,400 --> 00:08:12,470
one we've got here
94

95
00:08:12,810 --> 00:08:15,810
and the cellForRowAt indexPath.
95

96
00:08:15,990 --> 00:08:24,720
So this is going to tap into that cell that gets created inside our super view and it taps into the
96

97
00:08:24,720 --> 00:08:30,000
cell at the current indexPath. And then we're going to take that cell and then we're going to add some
97

98
00:08:30,000 --> 00:08:31,450
more things to it.
98

99
00:08:31,590 --> 00:08:34,590
And that cell is already a swipe cell,
99

100
00:08:34,620 --> 00:08:41,160
but we're going to modify it further by changing the textLabel to the current category.
100

101
00:08:41,160 --> 00:08:45,310
And then finally, we're going to return cell after all of that work.
101

102
00:08:45,510 --> 00:08:51,310
So when this gets called, the first thing it does is, because we call super,
102

103
00:08:51,360 --> 00:08:57,400
it goes into our superclass and triggers the code inside our cellForRowAt indexPath,
103

104
00:08:57,600 --> 00:09:03,720
at which point, it creates a new cell from the prototype cell called Cell and it gets created as a 
104

105
00:09:03,720 --> 00:09:04,900
SwipeTableViewCell.
105

106
00:09:04,950 --> 00:09:11,190
It sets the cells delegate as this current class which is the SwipeTableViewController to enable
106

107
00:09:11,190 --> 00:09:13,020
all of our delegate methods to work,
107

108
00:09:13,160 --> 00:09:20,350
and then it returns that cell. And that cell when it gets returned, it gets placed into here.
108

109
00:09:20,640 --> 00:09:27,780
At which point, we further modify it by changing the textLabel, and finally, return the cell to our current
109

110
00:09:27,780 --> 00:09:31,930
table view inside our CategoryViewController class.
110

111
00:09:31,980 --> 00:09:39,300
So it seems a little bit roundabout and it's all in the name of trying to modularize our code and trying
111

112
00:09:39,300 --> 00:09:43,020
to reduce repetition and keep our code dry.
112

113
00:09:43,050 --> 00:09:49,100
So let's go ahead and hit run and see if our app actually runs and produces those cells
113

114
00:09:49,230 --> 00:09:50,460
or will it crash and burn.
114

115
00:09:50,460 --> 00:09:55,830
So the moment of truth is now. So the first good sign is that we haven't had any errors and we've
115

116
00:09:55,830 --> 00:10:01,730
got both of our Category cells with the textLabel.text filled out correctly.
116

117
00:10:02,080 --> 00:10:05,390
Now, the question is, are these swipe cells?
117

118
00:10:05,410 --> 00:10:11,090
Because if it only use the code here, then they're just going to be normal UITableViewCells.
118

119
00:10:11,260 --> 00:10:17,650
But if our inheritance from the superclass worked correctly, then we should be able to click and drag.
119

120
00:10:18,010 --> 00:10:20,310
And there you go. There's our delete button.
120

121
00:10:20,530 --> 00:10:25,640
Now, if you click the delete button at this time point, it will crash your app.
121

122
00:10:25,720 --> 00:10:32,500
And the reason is because it triggers this particular delegate method which is going to try and remove
122

123
00:10:32,800 --> 00:10:37,970
the last row in our table view, but we haven't removed it from our data source.
123

124
00:10:38,050 --> 00:10:45,580
So the incompatibility is going to lead to this error where it says, "Invalid number of rows in section."
124

125
00:10:45,580 --> 00:10:53,440
So in order for that to work, we have to update our model. Now, because we can't call category inside our
125

126
00:10:53,440 --> 00:10:54,380
superclass,
126

127
00:10:54,430 --> 00:11:00,040
you have to realize that your superclass must know nothing about its subclasses, so we cannot use any
127

128
00:11:00,040 --> 00:11:03,830
of these bits of code. But we can trigger a function call.
128

129
00:11:03,910 --> 00:11:06,970
So let's create a function down here.
129

130
00:11:07,240 --> 00:11:12,820
So we'll call it updateModel and the external parameter will be "at,"
130

131
00:11:12,850 --> 00:11:16,370
so we can call it like updateModel at this particular indexPath.
131

132
00:11:16,570 --> 00:11:23,910
But inside the function, we'll just call it indexPath and it's going to be of data type indexPath.
132

133
00:11:24,290 --> 00:11:30,870
And inside this function is where we will update our data model.
133

134
00:11:31,540 --> 00:11:34,540
Okay. So, now we need to call it over here,
134

135
00:11:34,570 --> 00:11:42,730
so we're going to call updateModel at the indexPath which is going to be the same one that triggered
135

136
00:11:42,790 --> 00:11:44,480
this delete delegate method.
136

137
00:11:44,650 --> 00:11:46,950
So we'll call it indexPath.
137

138
00:11:47,020 --> 00:11:51,460
And because we're inside a closure, we always have to add the keywords "self."
138

139
00:11:51,460 --> 00:11:59,080
And now we can cut this block of code and we can go into our CategoryViewController.
139

140
00:11:59,110 --> 00:12:05,920
Now, inside our CategoryViewController, under the Data Manipulation Method section, we've got save,
140

141
00:12:06,100 --> 00:12:14,200
we've got load, and now we're going to create a delete section and we'll call it Delete Data From Swipe.
141

142
00:12:14,230 --> 00:12:21,700
Now, instead of creating a method inside our current class, I'm going to override and call the superclass
142

143
00:12:21,700 --> 00:12:25,980
method which we named updateModels,
143

144
00:12:26,170 --> 00:12:30,960
so override updateModels at indexPath,
144

145
00:12:31,120 --> 00:12:37,260
wnd we're going to override that updateModel method that was specified over here.
145

146
00:12:37,480 --> 00:12:46,150
So when our deleteAction happens, it's going to call updateModels passing in an indexPath, at which
146

147
00:12:46,150 --> 00:12:46,600
point,
147

148
00:12:46,600 --> 00:12:53,150
not really very much happens, but we can tap into it over here by overriding it.
148

149
00:12:53,350 --> 00:12:58,900
So this is where we're going to paste that block of code and I'm going to uncomment it and shift it
149

150
00:12:58,900 --> 00:13:05,700
to the left a bit using command left square bracket, and this should take care of updating our model.
150

151
00:13:05,710 --> 00:13:08,290
So let's run an app and see if it works.
151

152
00:13:08,290 --> 00:13:12,070
All right so let's add a "New Category,"
152

153
00:13:13,160 --> 00:13:19,480
hit Add. And let's just check to make sure that we've got a Delete button when we swipe on it.
153

154
00:13:19,520 --> 00:13:21,760
So that comes from our superclass.
154

155
00:13:21,900 --> 00:13:30,610
And now if I hit the Delete button, you can see that this delegate method deleted our category from our
155

156
00:13:30,620 --> 00:13:31,540
data model.
156

157
00:13:31,550 --> 00:13:37,820
So this is more of an advanced example of some of the things that we learned on objects and classes and inheritance,
157

158
00:13:37,910 --> 00:13:44,810
especially. And it's really, really key that you understand how subclasses, superclasses, overriding, how
158

159
00:13:44,810 --> 00:13:46,000
all of this works.
159

160
00:13:46,130 --> 00:13:53,720
So it's important that you play around with this updateModel function and also where you override it
160

161
00:13:53,770 --> 00:13:54,690
over here.
161

162
00:13:54,800 --> 00:14:05,260
For example, if we create a print statement here that just says, "Item deleted" from the superclass, and
162

163
00:14:05,260 --> 00:14:08,170
then we go over to our CategoryViewController.
163

164
00:14:08,500 --> 00:14:14,430
If we run our app as is, we are not going to get that print statement in here.
164

165
00:14:15,560 --> 00:14:22,550
And I'm going to show you by running our app and creating new category, hit Add, and I'm going to swipe it
165

166
00:14:22,550 --> 00:14:23,550
to delete it.
166

167
00:14:23,720 --> 00:14:24,830
No print statement.
167

168
00:14:25,100 --> 00:14:30,450
And the reason is because we've overridden how that method should function.
168

169
00:14:30,500 --> 00:14:41,320
But if we made a call to the super updateModels(at: indexPath) method, then we will get that print statement.
169

170
00:14:41,600 --> 00:14:44,220
So let's add a new category.
170

171
00:14:44,270 --> 00:14:52,880
And now if I swipe and delete, you can see item deleted from superclass. And that's all because of this
171

172
00:14:52,880 --> 00:14:55,720
call to the superclass method.
172

173
00:14:55,730 --> 00:15:01,950
So, essentially, what's happening is that our deletion triggers this delegate method.
173

174
00:15:01,950 --> 00:15:10,250
This delegate method has a closure which triggers the updateModels(at: indexPath) and it passes in the
174

175
00:15:10,250 --> 00:15:17,630
indexPath of the cell that got swiped. That calls this function over here which has a print statement,
175

176
00:15:18,140 --> 00:15:26,870
but this function is overridden in the subclass. And that subclass can either call the superclass method
176

177
00:15:26,930 --> 00:15:34,670
in order to run all the code that's currently inside here or it can simply override it without the need
177

178
00:15:34,670 --> 00:15:37,030
for any of the superclass functionality.
178

179
00:15:37,310 --> 00:15:44,260
So if all of that makes sense, then it's time for your next challenge.
179

180
00:15:44,510 --> 00:15:51,440
And that is, of course, the fact that we have a TodoListViewController which is also going to now
180

181
00:15:51,440 --> 00:15:57,460
subclass the SwipeTableViewController, instead of a
181

182
00:15:57,470 --> 00:15:58,760
UITableViewContnroller.
182

183
00:15:58,760 --> 00:16:05,860
So the challenge is for you to implement that swipe cell functionality inside the TodoListViewController,
183

184
00:16:06,350 --> 00:16:12,920
and you will need to understand subclassing, superclassing, and all of the things that we've done over
184

185
00:16:12,920 --> 00:16:13,660
here
185

186
00:16:13,910 --> 00:16:21,590
in order to make it work and complete the challenge. If you need, it might be worth reviewing some of
186

187
00:16:21,590 --> 00:16:30,050
the lectures earlier on where we talked about objects, classes, inheritance, and having a look at the steps
187

188
00:16:30,050 --> 00:16:38,300
that we went through to update our CategoryViewController to be a subclass of SwipeTableViewController.
188

189
00:16:38,450 --> 00:16:44,480
But this is quite challenging and I suspect that it might take you a little while to figure everything
189

190
00:16:44,480 --> 00:16:51,140
out. But if you do get it right, then you'll know for sure that all of these concepts made sense to you.
190

191
00:16:51,170 --> 00:16:56,820
So rather than proving it to anyone else, prove it to yourself that you've understood everything.
191

192
00:16:57,050 --> 00:17:01,910
So go forth and struggle, and I will see you on the other side.
