How it works
A Stepper is a control that performs increment and decrement actions, letting people adjust a value in discrete steps. Reach for it when a quantity changes by a fixed amount one tap at a time — counts, ratings, or any setting where the user wants precise nudges rather than the free dragging of a Slider. It pairs a descriptive label with a pair of stepper buttons, and it can bind directly to a value while keeping that value within a range you define.
Bind a value with the value:in: initializer
The most direct initializer takes a
Bindingto the value to adjust and aClosedRangethat constrains it.Stepperincrements or decrements the bound value as the user taps, clamping it to the bounds you supply. In the example,Stepperis created withvalue: $quantityandin: 0...10, so tapping never drivesquantitybelow 0 or above 10.Drive the binding from @State
Because
Stepperwrites through a two-wayBinding, it needs a source of truth to mutate. Here that source is the@State private var quantityproperty; the$quantityprojected value passes the binding toStepper, and each tap updatesquantityin place and re-renders any view that reads it.Label the control with a title string
The first argument is the control's label, describing what the buttons adjust.
Stepperaccepts aString(or a title-and-views builder) and places it alongside the increment and decrement controls. The example passes the interpolated string"Quantity: \(quantity)", so the label restates the live value each time it changes.Set the step size with step:
By default
Stepperchanges the value by 1 per tap, but thestep:parameter lets you choose any stride. Addstep: 2to the existingvalue: $quantity, in: 0...10call and each tap movesquantityby two rather than one, while thein:range still clamps the result.Compose it with view modifiers
Stepperconforms toView, so it participates in the normal modifier chain and layout system. In the example.padding()is applied to inset the control; you can attach further modifiers — disabling, styling, or layout — exactly as you would to any other SwiftUI view.
in: 0...10 to in: 0...3 and watch the increment button stop responding once quantity reaches the upper bound.Example & preview
Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.
struct StepperDemo: View {
@State private var quantity = 2
var body: some View {
Stepper("Quantity: \(quantity)", value: $quantity, in: 0...10)
.padding()
}
}