How it works
ProgressViewStyleConfiguration carries the properties of a progress view into the style that draws it. When you create a custom ProgressViewStyle, SwiftUI hands your makeBody(configuration:) method one of these values describing the progress view it should render — its label and its current completion. Reach for it whenever the built-in progress styles aren't enough and you want full control over how progress is presented while still letting each ProgressView supply its own content and value.
Receive the configuration in makeBody(configuration:)
A custom style conforms to ProgressViewStyle and implements makeBody(configuration:), which SwiftUI calls once per progress view. The single parameter is a ProgressViewStyleConfiguration that stands in for the view being styled. In the example,
BarStyledeclaresfunc makeBody(configuration: ProgressViewStyleConfiguration) -> some Viewand returns aVStackbuilt entirely from that configuration.Place the view's content with configuration.label
The label property exposes the content the progress view was given — a type-erased view you position wherever your layout calls for it, rather than supplying your own text. The example renders
configuration.labelat the top of the stack and styles it with.font(.headline), so each ProgressView keeps its own label while the style controls placement.Read progress from configuration.fractionCompleted
fractionCompleted is an optional Double between 0 and 1 that reports how far along the work is, or nil for indeterminate progress. The example feeds it straight into
ProgressView(value: configuration.fractionCompleted)to draw the bar, and because it is optional it usesif let fraction = configuration.fractionCompletedto show a percentage only when a definite value exists.Compose your own presentation around those members
Because makeBody returns some View, you assemble the label and fraction into any layout and decorate it freely. The example wraps them in a
VStack, tints the inner bar with.tint(.green), and derives a caption withText("\(Int(fraction * 100))%")— all driven by the configuration rather than hard-coded content.Attach the style with progressViewStyle()
Your custom style takes effect when applied to a progress view via the progressViewStyle(_:) modifier, which is also what triggers SwiftUI to build and pass the configuration. The example creates a
ProgressView(value: 0.65)with aLabel("Downloading", systemImage: "arrow.down.circle")and applies.progressViewStyle(BarStyle()), so 0.65 arrives as fractionCompleted and the label arrives as configuration.label.
ProgressView(value: 0.65) to ProgressView() with no value, and the if-let on configuration.fractionCompleted will fail, showing how the configuration reports indeterminate progress as nil.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 ProgressViewStyleConfigurationDemo: View {
struct BarStyle: ProgressViewStyle {
func makeBody(configuration: ProgressViewStyleConfiguration) -> some View {
VStack(alignment: .leading, spacing: 6) {
configuration.label
.font(.headline)
ProgressView(value: configuration.fractionCompleted)
.tint(.green)
if let fraction = configuration.fractionCompleted {
Text("\(Int(fraction * 100))%")
.font(.caption)
.foregroundStyle(.secondary)
}
}
}
}
var body: some View {
ProgressView(value: 0.65) {
Label("Downloading", systemImage: "arrow.down.circle")
}
.progressViewStyle(BarStyle())
.padding()
}
}