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