As it happens every year in WWDC, Apple came to announce new development tools and bring advancements to existing ones. Some of them are big, some others are more subtle and not that apparent until they get discovered.
Such a small but quite interesting and useful addition is a brand new view modifier in SwiftUI called ButtonRepeatBehavior. Its purpose is pretty straightforward, and that is to let users repeat a button’s action repeatedly while pressing and holding it.
Let’s get to know it.
So far there was just the Stepper
Before WWDC 2023, the only control that allowed us to increase or decrease a value repeatedly by long pressing on any of its buttons was the Stepper; a horizontal control that consists of two buttons and a label where we can show the current value. Stepper is ideal in order to adjust numerical values that should change incrementally.
For example, we can create a Stepper like this:
1 2 3 4 5 6 7 8 9 10 |
struct ContentView: View { @State private var volume = 50 var body: some View { Stepper(“Volume \(volume)“, value: $volume, in: 0…100) .padding(.horizontal) } } |
This will display a Stepper like this:
We can increase or decrease the volume in the above example by tapping on the plus or minus buttons. We can also press and hold on any of the buttons to repeat the action until we release them.
However, we may want to use custom buttons instead of the Stepper sometimes. For instance, we may want to use different icons, shapes, colors, or sizes for our buttons. We may want to use vertical buttons instead of horizontal ones. Or we may want to use buttons for other purposes than simply adjusting numerical values.
Doing so had not been easy up until now, as it required significant amount of manual work involving resorting to UIKit along the way. But not anymore, as a SwiftUI native solution has finally arrived.
The ButtonRepeatBehavior
In cases like those described above, we can use the brand new ButtonRepeatBehavior view modifier in SwiftUI. This modifier provides the Stepper functionality to custom buttons when they are pressed and held. When applying this modifier, we can supply any of the following three three options as argument:
enabled
: This option enables repeating the button action on long press with some delay and interval.disabled
: This option disables repeating the button action.automatic
: This option lets SwiftUI decide how to handle the button press, and it’s usually equal to thedisabled
option.
Suppose, for example, that we want to create two custom buttons that would increase and decrease the volume value, which should be shown in a Text view. We want our buttons to be rounded with the “+” and “-” symbols as labels. But we also want our buttons to repeat their actions when they are pressed and held.
We can achieve that using custom buttons like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
struct ContentView: View { @State private var volume = 50 var body: some View { VStack { Text(“Volume \(volume)“) .font(.largeTitle) HStack(spacing: 30) { // The first button to decrease the volume. Button(action: { volume -= 1 }) { Image(systemName: “minus”) .font(.title) .frame(width: 44, height: 44) } .buttonStyle(.bordered) .clipShape(Circle()) // Enable repeating the action with the buttonRepeatBehavior modifier! .buttonRepeatBehavior(.enabled) // The second button to increase the volume. Button(action: { volume += 1 }) { Image(systemName: “plus”) .font(.title) .frame(width: 44, height: 44) } .buttonStyle(.bordered) .clipShape(Circle()) // Enable repeating the action with the buttonRepeatBehavior modifier! .buttonRepeatBehavior(.enabled) } } } } |
This will display two custom buttons like this:
We can increase or decrease the volume by tapping on the plus or minus buttons. But most importantly, we can also press and hold on any of the buttons to repeat the action until we release them.
Conclusion
Personally I believe that the ButtonRepeatBehavior view modifier has been a much anticipated capability in SwiftUI. As you see, it is a convenient and quite useful feature that provides an alternative solution to the Stepper; the one-direction way to go in order to repeat an action on long press up until now. From now on, custom buttons with repeatable actions are possible, while their look can match the UI of the rest of the app.
Note that ButtonRepeatBehavior is available in iOS 17 and macOS 14 (Sonoma) and later.
Thanks for reading!
Download the demo project from this link.