Mastering Forms in SwiftUI: Creating and Styling

Mastering Forms in SwiftUI: Creating and Styling

Learn how to create and customize the appearance of data-entry interfaces using forms in SwiftUI apps.

Applications, in order to deliver value to their user, often rely on user-generated data to work with. A reminders app needs reminders, a calendar app needs events, a contacts app needs contact information, and apps that rely on tracking, in general, need the user to input the information in the app.

User-created content comes in many shapes and forms and one of the most common use cases for user input is by presenting a form for them to fill.

Forms in the Calendar, Reminders and Contacts apps on iOS 18.

Forms serve as the backbone for user interaction, presenting an interface for data entry. Whether it's signing up for a service, making a purchase, or providing feedback, they are everywhere.

On SwiftUI the Form container provides a standardized look and feel for data input experiences, very similar to the List container. The different types of views and controls you place inside it will be organized in a list-like fashion, with scrolling working and the ability to create sections.

Forms

To create a form in SwiftUI use the Form view and place the views and controls you need inside the content block.

Form {
    Section {
        TextField("First Name", text: $firstName)
        TextField("Last Name", text: $lastName)
        TextField("Company", text: $company)
    }
    
    Section {
        TextField("Phone", text: $phone)
    }
    
    Section {
        TextField("Email", text: $email)
    }
}
.navigationTitle("New Contact")
#if os(macOS)
.padding()
#endif

When creating multi-platform apps, the way the form will render the views and controls will automatically adapt to present them in the most appropriate way for that platform.

Grouped layout for iOS and iPadOS apps and columns layout for macOS apps

Form Layout

To better organize the fields in your form use the Section view. Its purpose is to visually group fields that have something in common.

Form {
    Section {
        TextField("First Name", text: $firstName)
        TextField("Last Name", text: $lastName)
        TextField("Company", text: $company)
    }
    
    Section {
        TextField("Phone", text: $phone)
        TextField("Email", text: $email)
    }
    
    Section {
        TextField("Phone", text: $professionalPhone)
        TextField("Email", text: $professionalEmail)
    }
}

A section in a form can have a header and/or a footer view associated with it, providing further explanation of the purpose of that particular part of the form.

Form {
    Section {
        TextField("First Name", text: $firstName)
        TextField("Last Name", text: $lastName)
        TextField("Company", text: $company)
    }
    
    Section {
        TextField("Phone", text: $phone)
        TextField("Email", text: $email)
    } header: {
        Text("Personal Information")
    }
    
    Section {
        TextField("Phone", text: $professionalPhone)
        TextField("Email", text: $professionalEmail)
    } header: {
        Text("Professional Information")
    }
}

The footer of a section is often used to present form validation messages when a field is empty or is filled with invalid information. It can also further explain an aspect of a particular field or group of fields in the form.

Section {
    SecureField("Password", text: $textForSecureField)
} footer: {
    Text("Invalid password. Please use a minimum of 8 characters, mixing uppercase and lowercase letters, numbers and symbols.")
        .foregroundStyle(.red)
}

Form Style

The appearance of Forms in SwiftUI can be set using the formStyle(_:) modifier. There are three different form styles available:

Automatic Style

It is the default style setting, but if you want to enforce it, by setting the style to automatic you will leave the system to decide what is the most appropriate way to render the form.

Form {
    Section {
        TextField("First Name", text: $firstName)
        TextField("Last Name", text: $lastName)
        TextField("Company", text: $company)
    }
}
.formStyle(.automatic)
Automatic style forms on iOS, iPadOS and macOS

Columns Style

By setting the form style to columns the form will be organized in two columns. The first one to display the labels associated with the form fields trailing aligned and the second one will display the values associated with the labels leading aligned.

Form {
    Section {
        TextField("First Name", text: $firstName)
        TextField("Last Name", text: $lastName)
        TextField("Company", text: $company)
    }
}
.formStyle(.columns)

To better take advantage of this form layout use the LabeledContent view to wrap the fields that benefit from having a label associated with them.

LabeledContent("Email") {
    TextField("Email", text: $email)
}
Columns style forms on iOS, iPadOS and macOS

As you can see, the columns layout in iOS and iPadOS requires further customization on the appearance of the form to appear properly.

Grouped Style

A form style with visually grouped rows and sections. By setting the form style to grouped you will receive the default look and feel of iOS applications, with leading aligned labels, trailing aligned controls and white background grouped rows. The overall form background is light gray.

Form {
    Section {
        TextField("First Name", text: $firstName)
        TextField("Last Name", text: $lastName)
        TextField("Company", text: $company)
    }
}
.formStyle(.grouped)
Grouped style forms on iOS, iPadOS and macOS

Useful modifiers

When working with Form in SwiftUI, most of the modifiers available for customizing the appearance of lists can be used to apply changes to how the elements inside the form are rendered.

For spacing and the appearance of sections, rows and separators, check the following modifiers:

To control the visibility of the labels of the data-entry fields in the form use the following modifiers: