What is SwiftUI Form
Table of Contents
What is SwiftUI Form
Form is one of a container view in SwiftUI that is designed for grouping controls used for modifying data entry.
One example that fits this use case is a settings view.
You can easily support sarunw.com by checking out this sponsor.
 
    AI Grammar: Correct grammar, spell check, check punctuation, and parphrase.
How to use SwiftUI Form
Form behaves similar to List view.
- It applies platform-appropriate style to views and controls that sit inside a form.
- You can group controls under Section, just like a list view.
You can construct a form like you create a List view. The only difference is you use a Form instead of a List view.
I will show you how to create a form from basic views and controls.
Form with TextField
We start by creating a simple form with one text field.
struct ContentView: View {
    // 1
    @AppStorage("deviceName") private var deviceName: String = ""
    
    var body: some View {
        NavigationStack {
            // 2
            Form {
                // 3
                TextField("Name", text: $deviceName)
            }
            .navigationBarTitle("Settings")
        }
    }
}1 Since Form is meant to manipulate a group of data entries. Most controls are probably backed by data. In this case, we use @AppStorage to make it persist across the app launch.
2 Form is a container view that wraps all of our controls.
3 We create a text field that binds to the deviceName variable.
 
Form with LabeledContent
Form also supports static content. In this case, I use LabeledContent to show the current iOS version.
struct ContentView: View {
    @AppStorage("deviceName") private var deviceName: String = ""
    
    var body: some View {
        NavigationStack {
            Form {
                TextField("Name", text: $deviceName)
                LabeledContent("iOS Version", value: "16.2")
            }
            .navigationBarTitle("Settings")
        }
    }
} 
Form with Toggle
You can keep adding controls to a form. I add a new Toggle that controls Wi-Fi here.
struct ContentView: View {
    @AppStorage("deviceName") private var deviceName: String = ""
    @AppStorage("wifi") private var isWifiEnabled: Bool = false
    
    var body: some View {
        NavigationStack {
            Form {
                TextField("Name", text: $deviceName)
                LabeledContent("iOS Version", value: "16.2")
                Toggle("Wi-Fi", isOn: $isWifiEnabled)
            }
            .navigationBarTitle("Settings")
        }
    }
} 
Add Section to a Form
If you have a lot of controls, you can use Section to group related items together.
In the following example, we create two groups.
- About
- Internet
struct ContentView: View {
    @AppStorage("deviceName") private var deviceName: String = ""
    @AppStorage("wifi") private var isWifiEnabled: Bool = false
    
    var body: some View {
        NavigationStack {
            Form {
                Section {
                    TextField("Name", text: $deviceName)
                    LabeledContent("iOS Version", value: "16.2")
                } header: {
                    Text("About")
                }
                Section {
                    Toggle("Wi-Fi", isOn: $isWifiEnabled)
                } header: {
                    Text("Internet")
                }
            }
            .navigationBarTitle("Settings")
        }
    }
} 
Add Picker to a Form
Settings usually include an option for users to choose from.
So, enum and Picker are common choices. Form also supports a picker view.
I create a new enum for an option, AutoJoinHotspotOption.
enum AutoJoinHotspotOption: String, CaseIterable, Identifiable {
    var id: Self {
        return self
    }
    
    case never
    case askToJoin
    case automatic
}Then, I present these options with a Picker view.
struct ContentView: View {
    @AppStorage("deviceName") private var deviceName: String = ""
    @AppStorage("wifi") private var isWifiEnabled: Bool = false
    @AppStorage("autoJoin") private var autoJoinOption: AutoJoinHotspotOption = .never
    
    var body: some View {
        NavigationStack {
            Form {
                Section {
                    TextField("Name", text: $deviceName)
                    LabeledContent("iOS Version", value: "16.2")
                } header: {
                    Text("About")
                }
                Section {
                    Toggle("Wi-Fi", isOn: $isWifiEnabled)
                    Picker("Auto-Join Hotspot", selection: $autoJoinOption) {
                        ForEach(AutoJoinHotspotOption.allCases) { option in
                            Text(option.rawValue)
                        }
                    }
                } header: {
                    Text("Internet")
                }
            }
            .navigationBarTitle("Settings")
        }
    }
}A picker renders with a menu style in iOS 16.
 
Add Button to a Form
The last control that I will add to the form is a button.
We add a button to reset all content and settings and put it in the new section at the bottom of the form.
struct ContentView: View {
    @AppStorage("deviceName") private var deviceName: String = ""
    @AppStorage("wifi") private var isWifiEnabled: Bool = false
    @AppStorage("autoJoin") private var autoJoinOption: AutoJoinHotspotOption = .never
    
    var body: some View {
        NavigationStack {
            Form {
                Section {
                    TextField("Name", text: $deviceName)
                    LabeledContent("iOS Version", value: "16.2")
                } header: {
                    Text("About")
                }
                Section {
                    Toggle("Wi-Fi", isOn: $isWifiEnabled)
                    Picker("Auto-Join Hotspot", selection: $autoJoinOption) {
                        ForEach(AutoJoinHotspotOption.allCases) { option in
                            Text(option.rawValue)
                        }
                    }
                } header: {
                    Text("Internet")
                }
                
                Section {
                    Button("Reset All Content and Settings") {
                        // Reset logic
                    }
                }
            }
            .navigationBarTitle("Settings")
        }
    }
} 
You can easily support sarunw.com by checking out this sponsor.
 
    AI Grammar: Correct grammar, spell check, check punctuation, and parphrase.
What is the difference between Form and List
With the example you see so far, you might wonder what the difference is between List and Form.
It is a reasonable question since Form in iOS uses the same appearance and style as an inset grouped list. So, there is no difference there.
But as mentioned earlier, Form applies a platform-appropriate style to its child views. So, the similarity between Form and List isn't guaranteed.
You will see a difference when you use Form on a platform where settings use a different design language from a List.
Here is an example of Form in macOS.
 
Compare it to List here.
 
Read more article about SwiftUI, Form, or see all available topic
Enjoy the read?
If you enjoy this article, you can subscribe to the weekly newsletter.
Every Friday, you'll get a quick recap of all articles and tips posted on this site. No strings attached. Unsubscribe anytime.
Feel free to follow me on Twitter and ask your questions related to this post. Thanks for reading and see you next time.
If you enjoy my writing, please check out my Patreon https://www.patreon.com/sarunw and become my supporter. Sharing the article is also greatly appreciated.
Become a patron Buy me a coffee Tweet ShareSwift private access level change in Swift 4
In Swift 4, there is a change in the private access level that means to end the use of fileprivate. Let's learn what it is all about.
Swift Ternary operator (?:)
The Ternary operator is quite similar to if-else statements, but it isn't the same. Let's learn what it is and how to use it.