All right, so we've got some really really cool functionality inside our Todoey app and we are now fully 1
persisting all of our data using Realm. 2
So, now that we've set up most of the backend and our data storage solution, it's time to think about 3
how we can improve the front-end. 4
And we're going to do just a few things to make our app a little bit easier on the eye because, at the 5
moment, truth be said, it is a very, very lean looking app. 6
And ideally, I kind of need to be able to delete categories if I no longer want them. 7
And at the moment, we don't really have any of that functionality because inside our TableView Delegate 8
Methods, when we tap on any of the rows, we need to take the user to the TodoListViewController, 9
the next view controller, 10
and so we can't really use that to delete the categories. 11
So what else can we do? 12
Well, we can implement something similar to what you see in your mail app. 13
You can reveal the delete button. And if you swipe a little bit further, you can actually automatically 14
delete the contents of that cell. 15
So let's think about how we can implement this. 16
And as always, you will usually find that CocoaPods is going to be your best friend. 17
One of the things I regularly do before I program anything UI or front-end related is to just go window 18
shopping on CocoaPods. So other people like going to the mall, 19
I like going on CocoaPods. 20
So let's go ahead and search for something like "swipe." 21
You can look through each of these libraries. 22
So let's have a look at the first one. You can see that it's got a cute little animation where it shows 23
you what the library is capable of doing. 24
And you can see that this is pretty much a copy of the mail app functionality that we were talking about 25
just now. 26
So this is brilliant. 27
We've found what we wanted in just one search. 28
So let's go over to the get her page and see how we can implement and use this. 29
So they've got a whole bunch of demos in terms of the different transition styles and expansion styles 30
and requirements. 31
And it also shows you how you can install it pretty easily. 32
So all we need is just to pod swipe sell kit so we know all about that. 33
So let's go ahead and implement it. 34
So I'm going to close down my project here. 35
I'm going to open up Terminal. 36
So let's go ahead and cd to it. 37
So the containing folder is currently on my desktop. 38
So I'm going to say cd towards here, and then I'm going to tag on another command, 39
and that's going to be open Podfile -a using the application Xcode and we're not initializing 40
a new pod file because we've already done so in order to use Realm. 41
So if I hit enter, it should find the right directory and open up my pod file. 42
So the part that I'm going to add here is going to be part SwipeCellKit. 43
And if you want to minimize typos, then just go ahead and paste it in. 44
And we're going to hit save and we're going to close this down. And we're going to say pod install, and 45
we'll let that run in the background. 46
All right. 47
So pods are installed. And now we can open up our Xcode workspace and we can work on it using our 48
SwipeCellKit. 49
So let's go ahead and implement it for our CategoryViewController. 50
So before we do anything, we, of course, first have to import the library that we're using which is called 51
SwipeCellKit and Xcode is, again, as always, being a little bit obstructive, 52
but we just need to hit it with a stick by using command B, 53
and that should allow it to figure out where the files for this SwipeCellKit pod exists. 54
Now, even though I've done this a few times, I just want to show you how you might use the documentation 55
of these libraries to learn to use new libraries and new frameworks. 56
And it's really, really simple. 57
So let's scroll down to the Documentation. 58
The first thing that it says is set the delegate property on 59
SwipeTableViewCell, and it's given us a little bit of example code. 60
So I'm just going to copy and paste this over here so that we can refer to it. So let's put this over 61
here and we'll just comment it out in case we mistakenly keep it in there or something. 62
So the first thing that you notice is that they dequeueReusableCell with a particular identifier, 63
and we've got all of that. 64
And it also wants to downcast it as a SwipeTableViewCell. 65
So let's go ahead and do that. 66
A SwipeTableViewCell. 67
There we go. 68
Now, I'm gonna actually collapse my left-hand side, so my text doesn't wrap and you can see it more clearly 69
this way. 70
And then the next thing they have is they set the cell's delegate to self. 71
So let's go ahead and do that as well. And we'll do it down here, 72
cell.delegate = self. 73
So that's the current view controller. And you should be reminded that whenever we're setting delegate 74
on anything, we probably have to move up here and do something with the protocol. 75
So let's read on. 76
And as you can see, it says, "Adopt the SwipeTableViewCellDelegate protocol." 77
So let's copy that and let's go over here and paste it in here. 78
Swipe table view self delegate. 79
Now, as I mentioned before, whenever you find yourself putting in new delegates, then it's usually a good 80
time to put in an extension. 81
So in our CategoryViewController, we don't actually yet have any extensions, so we can go ahead and create 82
a new one. 83
So outside the entire class, we're going to go and create a new extension. 84
So we'll just call it extension and it's going to extend CategoryViewCnontroller. CategoryViewCnontroller. 85
And the reason why we're extending it is because we want to use this SwipeTableViewCellDelegate. 86
So this is going to be the section that we're going to deal with all the Swipe Cell Delegate methods. 87
And just above it then, it's a good point to make a pragma MARK and say this is are SwipeCellDelegateMethods. 88
And you can see, we split up our entire view controller very nicely with these sections and extensions. 89
All right. 90
So the first error we get is that CategoryViewController does not conform to protocol 91
'SwipeTableViewCellDelegate.' 92
So we adopted this protocol in our CategoryViewController, but we actually don't have the delegate 93
methods that are required. 94
So Xcode will add the protocol stubs if you want or why don't we have a look back at the Documentation 95
and see what else is required. 96
So the next function here is a tableView method that allows you to editActionsForRow, and this 97
is something that comes from this SwipeCellKit. 98
So we can simply just copy this entire method and put it inside our extension. And we now have a delegate 99
method, 100
and that error goes away because this was the required delegate method. 101
So what does this code do? 102
Well, it's responsible for handling what should happen when a user actually swipes on the cells. And you 103
can see the first thing is to check and make sure that the orientation of the swipe is from the right. 104
And then we have this closure that handles what should happen when the cell gets swiped. 105
And finally, we add an image to that part of the cell that's going to show when we swipe on the cell, 106
and then we return this delete action as the response to a user swiping on the cell. 107
So we don't actually currently have an image code "delete" inside our Asset.xcassets. 108
We actually have nothing in here so far. But no matter because we can get it straight from 109
SwipeCellKits example app. 110
Now, you can actually download and git close the entire app to have a look at their example, 111
but in my case, I'm just gonna go into the Example folder, and then MailExample. 112
I'm going to go into their Assets.xcassets. I'm going to find the imageset called Trash. 113
And there is something here called Trash Icon.png. And here, I'm going to right-click and I'm going 114
to save image into my Downloads folder. 115
So, now that I've downloaded this thing called TrashIcon, I'm just going to rename it to delete-icon. 116
And that way, it makes a little bit more sense, rather than having the space in the name. And you'll see 117
very soon why. 118
And once you've renamed it, then you can safely drag it into your Assets.xcassets folder in the 119
left-hand pane here. 120
So we're going to put that in there and I'm going to adjust it to the to 2x position because it's actually 121
a 2x image. 122
Now, the next thing I want to do is go back into my CategoryViewController and I'm going to change 123
the name to whatever I called it just now. 124
And just to remind ourselves, it's called delete-icon. 125
So I'm going to delete dash icon. 126
So now what should happen is that when I run my app and I land on the CategoryViewController, when 127
I swipe from the right of the cell, then I should be able to trigger this closure. And inside here, and 128
at this point, I want to print "Item deleted." 129
Now, obviously, nothing's being deleted, but we're just testing our code out here. 130
And when I do swipe, it should show me the "delete-icon" as an image and the "Delete" text underneath that 131
icon. 132
Now, at this point, you might think that you can run your app. But if you do, the Apple actually crash. 133
Let's investigate why that is. 134
What's the reason for the crash? 135
When we run our app, you will get this error and it will crash your app. 136
Now, the reason for this is because it says, could not cast-- It could not turn a UITableViewCell 137
into a SwipeTableViewCell. 138
So how can we fix this issue? 139
Well, let's first stop our app and go into our Main.storyboard, So here, what we can do is we can select 140
our Category Cell and have a look on the right-hand pane. 141
If we go inside the Identity Inspector, we can specify a class that it should inherit from and also a 142
module where that class was located. 143
So here, instead of having it as a UITableViewCell, we can say that it is a 144
SwipeTableViewCell, and hit enter. And then we're going to change the module to SwipeCellKit, and hit save. 145
So let's go ahead and hit run and see if that fixes our problem. 146
All rigiht. 147
So our app no longer crashes, but it looks exactly the same as what we used to have. 148
But now these cells are actually no longer UITableViewCells. 149
They are, in fact, SwipeTableViewCells because that's what we changed its class to. 150
So if we click and swipe to the left, you can see that we've got this trash icon and the Delete message 151
showing. 152
Now, it's a little bit cramped in here because our cell is actually pretty short. 153
So why don't we go back and increase the size of our cell? 154
So let's go into viewDidLoad and let's say tableView.rowHeight equals, let's say, 80.0, 155
so that makes it 80 points high. 156
And let's run our app again and see if we've made it a little bit better. 157
So a lot of UI stuff you'll find yourself tweaking back and forth, running back and forth, just so that 158
you can see visually whether if you're happy with the effect. 159
So, now that looks pretty nice, 160
right? 161
And each of our items get a little bit more space and it doesn't look so bunched up anymore. 162
So, all right, 163
I'm pretty happy with that. 164
So let's test the functionality. When I click on the delete button, 165
I'm expecting this closure to happen and my print line to be executed and, indeed, it does. Every single 166
time I click on the delete button, then it gets deleted. 167
Now, it's no good just printing "Item deleted" into the console, the user can't see that. 168
So let's go ahead and replace this print statement with some real code. 169
And as it suggests, "handle the action by updating our model with deletion." 170
So as a challenge, I'd like you to pause the video and see if you can figure out how to use the indexPath 171
that we get back 172
that's going to tell us which row was swiped upon, and inside here, which row was selected to be deleted 173
when the user taps on that red button, and to use all of that information to delete the correct category 174
from our list of categories here. 175
So pause the video and give that a try 176
All right, so how did that go? 177
Well, as you know, we're going to be adding the code in here because it says that's where we should handle 178
the action. 179
And this is the closure that gets called when the user swipes on the cell and clicks on the delete button. 180
So inside here is where we're going to use our realm.write 181
in order to update our Realm, and the update that we want to make is we want to say realm.delete, and 182
the object we want to delete is the item at indexPath.row, so the row that was swiped on. And we're 183
going to look inside this collection of Results that we've called categories and remove the category 184
at that indexPath. 185
So we're going to say delete(categories[indexPath.row]) 186
Now, of course, realm.write can throw, 187
so we're going to wrap it inside a do 188
catch block. 189
And then we're going to mark realm.write with a try 190
keyword. 191
So the categories here is, if you remember, an optional, 192
so we have to somehow safely deal with it. So we can use optional binding to handle this. 193
So if we say if let categoryForDeletion = categories? two optional chain, indexPath.row, 194
then inside here we can perform the do catch block. And instead of deleting that, we can delete 195
the categoryForDeletion. 196
Now, because some of these are global variables and we're using it inside our closure here, then we have 197
to add self in front of them to explicitly say that they belong to the current class. 198
Now, finally, if all of that succeeded, then we can go ahead and make a call to tableView.reloadData 199
so that we call on data source methods and remove the last cell because it no longer exists 200
in our Realm database. 201
So let's give our app a go and run it to see what happens. 202
All right. 203
So we are going to add a new category, New Category. I'm not feeling very imaginative today. And go ahead 204
and hit Add and we're going to click and drag, and click delete. 205
And there we go. 206
Now, it's gone. All thanks to SwipeCellKit and our little bit of code. 207
So you might have noticed in our current version of the app that it's not quite the same as the mail app, 208
because in the mail app when you click and drag, you can actually drag further and just delete the 209
entire cell by that one swipe gesture. At the moment, 210
you have to do two gestures. You have to swipe and then delete. 211
So how can we implement the same thing that we have inside the mail app? 212
Well, let's head back over to the Documentation and continue reading. 213
So it says that optionally, you can implement the editActionsOptionsForRowAt method. 214
Now, that's a horribly named method, but it does allow us to customize behavior of the swipe actions. 215
And one of the options that we can specify is the expansion style. If we have a look up here at the demos, 216
we can see that the expansion style for destructive is exactly what we want, right? Where if you swipe further 217
than the delete action gets called without you having to tap on any of the other buttons. 218
So let's go ahead and copy this block of code over to our code. 219
We're going to put it below this delegate method here. 220
So right here. Now, there's two options that were specified in the Documentation. 221
One is the expansion style 222
and one is a transition style. 223
So let's have a look at what that border transition style looks like up here. 224
So you can see that in the demo, there's four different transition styles that they show. And border, basically, 225
just allows all the buttons to show up and increase in size at the same time, rather than drag or reveal. 226
So this is not something that we care about too much right now, 227
so I'm actually just going to delete that line of code. And all I'm interested in is this destructive 228
behavior. 229
Now, before we run our app, it's really important to realize this option will try to remove the last row 230
from your table view. 231
So before we can run our app, let's go ahead and delete this reloadData that we added previously. 232
Now, we're ready to go ahead and run our app and see if it works. 233
All right. 234
So let's add a new category, hit Add, and then we're going to click and drag a little bit, and you can see 235
that we've got that delete button show up, and then we're going to click and drag it a lot, and you can 236
see the entire cell simply disappears. 237
And our previous behavior still works, 238
we can still swipe a little bit, and then click delete to remove it as well. 239
And it's got a pretty neat animation when the library removes that row, as you can see when you do this, 240
right? 241
It just shrinks it down. 242
So that is all. Thanks to this destructive expansion style. And all we had to do is put in, what, five or 243
six lines of code for all of that to work. 244
So that's pretty neat, right? 245
Now, what about our 246
TodoListViewController? 247
What if we could have both the behavior of our checking and unchecking, as well as being able to delete 248
item, wouldn't that be neat? 249
So in that case, we would be able to click on the cell to check it and we would be able to click and 250
swipe it to just get rid of it. Because sometimes you want to see the task that you've ticked off and 251
sometimes, you know, you're so done with them that you just want to delete them. 252
So how can we implement that here? 253
Now, you might realize that all that you need is pretty much this extension, right? 254
And you could theoretically copy and paste it over here because it's much the same functionality that 255
we need. 256
But as always when you're copying pasting large blocks of code you should think to yourself, is there 257
a better way of doing this? 258
How can I keep my code more dry. 259
So in the next lesson, we're going to tackle this by creating a superclass that we're going to inherit 260
from. 261
So for all of that and more, I'll see you on the next lesson.