TechnologiesSwiftUI

Stepper struct

iOSmacOStvOSwatchOSvisionOS✓ renders

A control that performs increment and decrement actions.

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.

  1. Bind a value with the value:in: initializer

    The most direct initializer takes a Binding to the value to adjust and a ClosedRange that constrains it. Stepper increments or decrements the bound value as the user taps, clamping it to the bounds you supply. In the example, Stepper is created with value: $quantity and in: 0...10, so tapping never drives quantity below 0 or above 10.

  2. Drive the binding from @State

    Because Stepper writes through a two-way Binding, it needs a source of truth to mutate. Here that source is the @State private var quantity property; the $quantity projected value passes the binding to Stepper, and each tap updates quantity in place and re-renders any view that reads it.

  3. Label the control with a title string

    The first argument is the control's label, describing what the buttons adjust. Stepper accepts a String (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.

  4. Set the step size with step:

    By default Stepper changes the value by 1 per tap, but the step: parameter lets you choose any stride. Add step: 2 to the existing value: $quantity, in: 0...10 call and each tap moves quantity by two rather than one, while the in: range still clamps the result.

  5. Compose it with view modifiers

    Stepper conforms to View, 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.

Try it — Change 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.

Stepper.swift
struct StepperDemo: View {
    @State private var quantity = 2

    var body: some View {
        Stepper("Quantity: \(quantity)", value: $quantity, in: 0...10)
            .padding()
    }
}
Live preview
Quantity: 2
Quantity: 2
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →