NEW: Join my free 100 Days of SwiftUI challenge today! >>

Adding swipe to delete and EditButton

Paul Hudson    @twostraws   

Fully updated for Xcode 11.2

Before we’re done with this app, let’s make a handful of smaller changes that help polish up what we have.

First, what happens if the user looks at their order and decides against one of the items? Right now we can add items but can’t delete them, but this isn’t too hard to remedy.

Just like UIKit, SwiftUI works with tables using IndexSet – a collection of locations in its data. So, we can add a method to OrderView that accepts an IndexSet and uses it to delete those items from our order array:

func deleteItems(at offsets: IndexSet) {
    order.items.remove(atOffsets: offsets)
}

To connect that to SwiftUI, we need to add an onDelete() modifier to the ForEach that shows the menu items in the order. This accepts a closure that will be executed when deletion happens, and that closure must accept an IndexSet and delete those items – basically exactly what our deleteItems(at:) method already does.

Modify the first section in the OrderView form to this:

Section {
    ForEach(order.items) { item in
        HStack {
            Text(item.name)
            Spacer()
            Text("$\(item.price)")
        }
    }.onDelete(perform: deleteItems)
}

If the user wants to remove several items at a time, that’s also easy to do in SwiftUI. We just added the method to handle deletion, so now we can add an edit button to the navigation bar and let SwiftUI handle the rest. No, really!

Add this after the .listStyle(GroupedListStyle()) modifier in OrderView:

.navigationBarItems(trailing: EditButton())

SwiftUI already knows that an edit button should toggle the table between editing and non-editing mode, while also changing title between Edit and Done – another example of us getting the system default behavior for free.

Let’s move on to a second upgrade: why do we let users press the Place Order button if they haven’t added anything to their order? This doesn’t make sense, and we shouldn’t really allow it. So, let’s not allow it!

Here’s how that part of OrderView looks right now:

Section {
    NavigationLink(destination: CheckoutView()) {
        Text("Place Order")
    }
}

What we want is to disable that when there are no items in our order. Well, thanks to the power of SwiftUI we can do exactly that with the disabled() modifier, like this:

Section {
    NavigationLink(destination: CheckoutView()) {
        Text("Place Order")
    }
}.disabled(order.items.isEmpty)

If you run the app now you’ll find that you can add an item, go to the order screen, and delete that item, and Place Order will automatically become disabled as your cart becomes empty.

Finally, we’re displaying the total for our order in CheckoutView, but it’s not particularly prominent. To finish up, let’s bump up that text size:

Section(header:
    Text("TOTAL: $\(totalPrice, specifier: "%.2f")")
        .font(.largeTitle)
) {

Much better!

Further reading

SPONSORED Instabug helps you identify and resolve severe crashes quickly. You can retrace in-app events and know exactly which line of code caused the crash along with environment details, network logs, repro steps, and the session profiler. Ask more questions or keep users up-to-date with in-app replies straight from your dashboard. Instabug takes data privacy seriously, so no one sees your data but you! See more detailed features comparison and try Instabug's crash reporting SDK for free.

Similar solutions…

BUY OUR BOOKS
Buy Pro Swift Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift (Vapor Edition) Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Server-Side Swift (Kitura Edition) Buy Beyond Code

Was this page useful? Let us know!

Average rating: 5.0/5