read

It is very easy to create swipe action for your rows. But there are SwiftUI nuances that might not show the buttons when you swipe. I hope this will save you some hours.

Do NOT apply button style

Let’s start with a working example:

List {
    Text("Swipe this row from trailing edge")
        .swipeActions {
            Button("Reply", systemImage: "envelope.open") {}
        }
}

If you were to apply any button style (eg. system borderless or custom styles), then the button will NOT show up at all.

Button("Reply", systemImage: "envelope.open") {}
    .buttonStyle(.borderless) // <-- This will cause a problem

This is because for swipe, the button MUST be automatic style (the default).

SwiftUI made it easy to encounter this pitfall because you can apply a button style globally, or to any root view, and it will apply the same style to all children buttons. I know because I’ve spent hours to find one 🥲

If you have such global button style, then for swipe rows, you have to explicitly give it the automatic style.

Button("Reply", systemImage: "envelope.open") {}
    .buttonStyle(.automatic) // <-- Explicit and overiding

How to show button text?

The example code above will show the reply button with image only, as the row doesn’t have sufficient height for the text.

If you increase the row height, the text will show.

These are SwiftUI predefined and automatic behaviour, for now.

Does not work for LazyVStack

It is common to use ScrollView + LazyVStack instead of a List.

Unfortunately, swipeActions will only work with a List.

You should use a List, if possible, as the performance is better as it reuses the cells (backed by UICollectionView).

If you still want to support swipe in a LazyVStack, then you might want to use some library, which apply drag gestures to your view.


Image

@samwize

¯\_(ツ)_/¯

Back to Home