Your Second iOS & SwiftUI App

Nov 4 2021 · Swift 5.5, iOS 15, Xcode 13

Part 3: Managing Rows

27. Delete & Move Rows

Episode complete

Play next episode

About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 26. Swipe Actions Next episode: 28. Conclusion

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Heads up... You've reached locked video content where the transcript will be shown as obfuscated text.

To recap, we're going to let users delete books from their library in two ways. First, the swipe action we already set up, and second, via an edit button. We can make one library method to handle both cases, but seeing where the second case needs to be implemented will help us write that method. So in section view... we'll use a modifier on our ForEach view filled with BookRows, on delete. Put it right before the label style is set. You don't need this perform here. You can use trailing closure syntax, as usual in SwiftUI. So what is this index set that on delete gives us? In theory, on delete could be providing you multiple integers to represent what multiple rows to delete. In practice, for the time being, SwiftUI doesn't support multitouch for deletion, so you'll probably always be working with a single index. With that information in our brains, head back to library.swift. And let's write the delete method to deal with the deletion index set, regardless of how many rows it represents. First thing, change this from deleteBook to deleteBooks. Then add an index set parameter. We'll call it offsets for reasons which will become apparent in a moment. We'll also always have a section to work with. Our ForEachInSection view iterates through the book array value of a section key in sortedBooks, so the indexes we get here will match the indexes from sortedBooks. To delete the matching books, start by typing remove at to get autocomplete for the method we need, remove atOffsets. Now pass it the parameter from deleteBooks. At this point, we'll have removed the right books from sortedBooks, but they'll be hanging around in booksCache. We can fix that by forwarding that deletion along to booksCache via sortedBooks set accesser, which, as you can see from this error, we need to write anyway. To start on that, we'll also need to specify this part we already have as the get. The set is going to be nearly what we did in the sortBooks method, so copy and paste this bit. But here, we'll assign to sortedBooks a new value. That will take care of deleting the books themselves, but we should also delete their images. To do that, start by copying the booksCache before deletion occurs. After deletion, we'll use the difference method to figure out the changes between the new state of the cache and the old one. This returns a collection of changes, and we can loop through them. Now let's switch on the change to see what it might be. And let Xcode do the work for you here. Remove is a really the only case that we should be encountering here, so delete the insert option. And we can change to if case syntax instead of a switch, considering we're only doing something for this one case. It's only element that we'll actually need, so clean up the rest of that with underscores. And let's rename element to what it actually is, deletedBook. Set that book's image to nil, and you'll be done with the deleteBooks method. Now go back to section view. And jump to the delete swipe action. We don't have automatic access to an index set for deleted items from here, so we'll need to look up the index of the current book. We can do that by finding the first index in this section's books that has an ID that matches the book for this row, and if something has gone horribly wrong, just return. Now we can call deleteBooks. Turn the integer we have into an index set with this initializer and just pass along the section. Maybe wrap it in with animation as well. You can do the same in on delete, but that already gives you the index that you need, so it's more straightforward. The swipe action would work right now, but we don't yet have an edit button. You only need one more line of code to get that working, but it's a pretty powerful line. Up in content view, add a toolbar to your list. Passing in the initializer for EditButton. Now, when you live preview, if you swipe from right to left, you'll now get a delete button on any row. You can tap that button, or you can just swipe further to avoid having to tap. And for the alternative, tap the edit button and enter edit mode. That brings in a button for each row. Tap that button, and then you can hit the button on the other side to delete your books. What you can't do in edit mode is swipe left to do the same, but you can hit done and get right back to it. The other thing edit mode is great for is moving rows. Going off of on delete, you might guess that the modifier for that is on move, and you would be right. A difference here is that you won't just have an index set to work with, you'll also have an additional int. Indexes here refers to the original indexes of the rows you're moving. Again as with deletion, multitouch isn't supported yet, so it's probably only going to be a set with one number. What's definitely one number is the new offset. That's where the row, or potentially rows, are going to end up. To work with these parameters, let's add another library method below deleteBooks. This one will be called moveBooks. It'll take an old offsets index set and a new offset int. And we'll always have a section for this as well. Again, you'll be working with sortedBooks for that section. But you won't be calling remove this time, just move. And that's that. Now, back in section view... The move method will do all the hard work for you. You just need to call your library method with the appropriate three arguments. Now, if you build the app and go into edit mode, you'll have icons on the right to indicate that you can grab the rows and reorder them. You can move this out within the section it's in, but if you try to move it into another one, it gracefully doesn't let you.