Toggle

Use the snippet below to see all of the built-in styles.

1Toggle("Automatic", isOn: $myBool)
2    .toggleStyle(.automatic)
3
4Toggle("Button Toggle Style", isOn: $myBool)
5    .toggleStyle(.button)
6
7Toggle("Switch Toggle Style", isOn: $myBool)
8    .toggleStyle(.switch)

Create your style struct and have it conform to ToggleStyle. It is customary for all toggle styles to be named ...ToggleStyle. The Configuration type contains .label, .isOn, and .isMixed for you to use as you wish to style the button. It is up to you to use a gesture with an updating state if you want to have an isPressed appearance.

 1struct MyToggleStyle: ToggleStyle {
 2    func makeBody(configuration: Configuration) -> some View {
 3        VStack {
 4            configuration.label
 5            
 6            image(systemName: systemName(isOn: configuration.isOn))
 7        }
 8        .onTapGesture {
 9            configuration.isOn.toggle()
10        }
11        .overlay {
12            if configuration.isMixed {
13                warningBorder
14            }
15        }
16    }
17
18    func systemName(isOn: Bool) -> String {
19        isOn ? "hare" : "xmark.circle"
20    }
21
22    func image(systemName: String) -> some View {
23        Image(systemName: systemName)
24            .resizable()
25            .scaledToFit()
26            .frame(width: 50, height: 50)
27    }
28
29    var warningBorder: some View {
30        Rectangle()
31            .stroke(lineWidth: 3)
32            .foregroundStyle(.orange)
33    }
34}

In order to use the nice .toggleStyle(.myToggle) syntax, we must extend the ToggleStyle protocol. Without this, we would have to use .toggleStyle(MyToggleStyle()), which is now considered an old way of using styles.

1extension ToggleStyle where Self == MyToggleStyle {
2    static var myToggle: Self { .init() }
3}

See the toggle style in action by using the following code in your view.

1Toggle("My Toggle Style", isOn: $myBool)
2    .toggleStyle(.myToggle)

If you want to use a multi-value switch, consider this example. Note that the state property used here is initialized as @State private var sources = [false, false, false]. Using the index to retrieve the state values is not something I would ever recommend but I do not want to complicate this example by creating a new type just for this example.

1Toggle(sources: $sources, isOn: \.self) {
2    Text("Play with `isMixed`")
3}
4.toggleStyle(.myToggle)
5
6Toggle("Source 1/3", isOn: $sources[0])
7Toggle("Source 2/3", isOn: $sources[1])
8Toggle("Source 3/3", isOn: $sources[2])

Note that if the states are all false or mixed then the "parent" toggle will be considered "off" and when you turn it "on" it will change all of the states to true. The parent toggle will only be "on" if all the states are true and then if you turn it off all of the states will be turned to false simultaneously.

  • Under what contexts does the automatic style change?

Xcode Version: 16.1 beta 3
Official Apple Documentation