Neil Macy

Be Careful Using SwiftUI's buttonStyle Modifier With List swipeActions

SwiftUI has a really useful swipeActions modifier on List rows - see the SwiftUI docs here. It lets you add a swipe gesture to show action buttons on that row. For example, a delete button. (You've seen this in apps like Mail, where you swipe to get actions like Move or Archive/Delete.)

When I was adding it to an app recently, I found a bit of a strange bug. I just couldn't get the swipeActions to work; the gesture did nothing.

I discovered this article about swipeActions on samwize.com and it identified my bug:

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

The problem is, if you set a button style on a parent view, then it'll apply to all of the buttons within that view. That's usually a great thing about SwiftUI: you can apply a style to all subviews of a view by setting the modifier at a top level view. But for swipeActions to work, you'll have to explicitly use the modifier .buttonStyle(.automatic) on your buttons in swipeActions to set buttonStyle back to the default:

.swipeActions {
	Button {
		// some action
	} label: {
		Label("Some Action", systemImage: "some.action.image")
	}
	.buttonStyle(.automatic)
}

I think I understand the source of the problem - the buttonStyle has to be .automatic for the buttons to be rendered properly in swipeActions, and if you have some custom style then it could be really awkward to render.

But I strongly disagree with the solution the SwiftUI team have gone with, where the swipeActions modifier has no effect with a custom buttonStyle. Better to make the core action work, and break the styling, than to honour the styling and make the action silently fail.




If you liked this article, please consider buying me a coffee to support my writing.

Published on 10 February 2025