Skip to main content

Working with SwiftUI Forms and Input

1. Creating Forms

Property Value Description
Form Form Root view for creating forms in SwiftUI
Section Section Groups related form elements
TextField TextField Allows user input for text values
Picker Picker Provides selection from a list of options
Toggle Toggle Boolean switch for on/off states
Stepper Stepper Numeric input with increment/decrement controls

Example: Basic Form Structure

struct ContentView: View {
    @State private var name = ""
    @State private var age = 0
    @State private var isSubscribed = false

    var body: some View {
        Form {
            Section(header: Text("Personal Information")) {
                TextField("Name", text: $name)
                Stepper("Age: " + String(age), value: $age, in: 0...120)
            }

            Section(header: Text("Preferences")) {
                Toggle("Subscribe to newsletter", isOn: $isSubscribed)
            }
        }
    }
}
Note: The Form view automatically handles keyboard navigation and accessibility features.

2. Using TextField for Text Input

Property Value Description
.textFieldStyle(_:) TextFieldStyle Applies a style to the text field, such as rounded or bordered.
.onSubmit(of:action:) SubmitScope Triggers an action when the user submits input (e.g., presses return).
.onChange(of:perform:) Binding<String> Executes a closure when the text field's value changes.

Example: Basic TextField Usage

struct ContentView: View {
    @State private var userInput = ""

    var body: some View {
        TextField("Enter text", text: $userInput)
    }
}

Example: TextField with Submission Handling

struct ContentView: View {
    @State private var userInput = ""

    var body: some View {
        TextField("Type something", text: $userInput)
            .onSubmit {
                print("Submitted: \"\(userInput)\"")
            }
    }
}

Example: TextField with Validation

struct ContentView: View {
    @State private var userInput = ""
    @State private var isInvalid = false

    var body: some View {
        TextField("Enter name", text: $userInput)
            .onChange(of: userInput) { newValue in
                isInvalid = newValue.count < 3
            }
            .textFieldStyle(RoundedBorderTextFieldStyle())
            .disabled(isInvalid)
    }
}

3. Using SecureField for Passwords

Property Value Description
SecureField SecureField<String> A SwiftUI view for secure text input, typically used for passwords

Example: SecureField in a Form

struct LoginForm: View {
    @State private var password = ""

    var body: some View {
        Form {
            Section(header: Text("Login")) {
                SecureField("Password", text: $password)
                    .autocapitalization(.none)
                    .disableAutocorrection(true)
            }
        }
    }
}
Note: SecureField automatically masks input characters and does not support text selection or copying.
Warning: Never log or store passwords in plain text. Always use secure storage mechanisms like Keychain Services.

4. Using Picker for Selection

Property Value Description
selection Binding<String> Binds the selected value to a state variable
label Text Displays the label for the picker
menu Menu Displays the picker as a menu (iOS 16+)

Example: Basic Picker Usage

struct ContentView: View {
    @State private var selectedFruit = "Apple"
    
    let fruits = ["Apple", "Banana", "Orange", "Grape"]
    
    var body: some View {
        Form {
            Picker("Select a fruit", selection: $selectedFruit) {
                ForEach(fruits, id: \.self) { fruit in
                    Text(fruit)
                }
            }
        }
    }
}

Example: Picker with Custom Labels

struct ContentView: View {
    @State private var selectedColor = "Red"
    
    let colors = [
        (name: "Red", hex: "#FF0000"),
        (name: "Green", hex: "#00FF00"),
        (name: "Blue", hex: "#0000FF")
    ]
    
    var body: some View {
        Form {
            Picker("Select a color", selection: $selectedColor) {
                ForEach(colors, id: \.name) { color in
                    HStack {
                        Text(color.name)
                        Spacer()
                        Text(color.hex).foregroundColor(.secondary)
                    }
                }
            }
        }
    }
}
Note: The Picker view in SwiftUI is designed to work with a collection of values, typically strings or enums. It supports both Text and custom views for each item in the selection list.
Warning: When using Picker inside a Form, ensure that the selection variable is properly initialized to avoid unexpected behavior or crashes.

5. Using DatePicker for Dates

Property Value Description
date Date The selected date value
displayedComponents DatePickerComponents Defines which date components are displayed (e.g., .date, .hourAndMinute)
minimumDate Date? Minimum selectable date
maximumDate Date? Maximum selectable date

Example: Basic DatePicker Usage

struct ContentView: View {
    @State private var selectedDate = Date()
    
    var body: some View {
        DatePicker("Select Date", selection: $selectedDate, displayedComponents: .date)
    }
}

Example: DatePicker with Time

struct ContentView: View {
    @State private var selectedDateTime = Date()
    
    var body: some View {
        DatePicker(
            "Select Date and Time",
            selection: $selectedDateTime,
            displayedComponents: [.date, .hourAndMinute]
        )
    }
}

Example: DatePicker with Date Range

struct ContentView: View {
    @State private var selectedDate = Date()
    let minDate = Calendar.current.date(byAdding: .day, value: -30, to: Date())!
    let maxDate = Calendar.current.date(byAdding: .day, value: 30, to: Date())!
    
    var body: some View {
        DatePicker(
            "Select Date",
            selection: $selectedDate,
            displayedComponents: .date,
            minimum: minDate,
            maximum: maxDate
        )
    }
}
Note: The displayedComponents parameter allows you to control which parts of the date are shown in the picker. Common values include .date, .hourAndMinute, and .time.

6. Using Stepper for Increments

Property Value Description
value Int The current value of the stepper
increment Int The amount to increment by (default is 1)
step Int The step size for each increment (default is 1)

Example: Basic Stepper Usage

struct ContentView: View {
    @State private var count = 0

    var body: some View {
        VStack {
            Text("Count: \(count)")
            Stepper("Increment", value: $count)
        }
    }
}

Example: Stepper with Custom Increment

struct ContentView: View {
    @State private var count = 0

    var body: some View {
        VStack {
            Text("Count: \(count)")
            Stepper("Increment by 5", value: $count, step: 5)
        }
    }
}

7. Using Slider for Ranges

Property Value Description
value Double The current value of the slider
range Range<Double> The minimum and maximum values the slider can take
step Double Incremental steps for slider movement (optional)

Example: Basic Slider Usage

struct ContentView: View {
    @State private var sliderValue = 50.0

    var body: some View {
        VStack {
            Text("Value: \(Int(sliderValue))")
            Slider(value: $sliderValue, in: 0...100)
        }
    }
}

Example: Slider with Step

struct ContentView: View {
    @State private var sliderValue = 0.0

    var body: some View {
        VStack {
            Text("Value: \(Int(sliderValue))")
            Slider(value: $sliderValue, in: 0...100, step: 5.0)
        }
    }
}
Note: The Slider in SwiftUI is a two-way binding component, meaning it updates the state variable and reflects changes back to the UI.

8. Using Toggle for Boolean Values

Property Value Description
isOn Binding<Bool> The binding to the Boolean value that determines the toggle's state

Example: Basic Toggle Usage

struct ContentView: View {
    @State private var isSwitchOn = false

    var body: some View {
        Toggle("Enable Feature", isOn: $isSwitchOn)
    }
}

Example: Toggle with Custom Label

struct ContentView: View {
    @State private var notificationsEnabled = false

    var body: some View {
        Toggle(isOn: $notificationsEnabled) {
            Text("Enable Notifications")
                .font(.headline)
        }
    }
}
Note: The isOn binding must be a @State or @Binding property to allow SwiftUI to update the toggle's state.

9. Using ColorPicker for Colors

Property Value Description
ColorPicker ColorPicker("Choose a color", selection: $color) Displays a color picker for selecting colors

Example: Basic ColorPicker Usage

<ColorPicker("Choose a color", selection: $color)>
</ColorPicker>
Note: The ColorPicker is available in iOS 13 and later.

10. Implementing Form Validation

Property Description Usage
ValidationState Represents the validation state of a form field .valid, .invalid, .pending
errorMessage Displays error message for invalid input String value shown to user
isInvalid Boolean indicating if field is invalid Used to conditionally style fields

Example: Basic Form Validation

struct ContentView: View {
    @State private var name = ""
    @State private var email = ""
    @State private var isNameValid = true
    @State private var isEmailValid = true

    var body: some View {
        Form {
            TextField("Name", text: $name)
                .onChange(of: name) { _ in
                    isNameValid = !name.isEmpty
                }
            TextField("Email", text: $email)
                .onChange(of: email) { _ in
                    isEmailValid = email.contains("@")
                }
            Button("Submit") {
                // Handle submission
            }
            .disabled(!isNameValid || !isEmailValid)
        }
    }
}

Example: Custom Validation Rule

struct EmailValidator {
    static func isValid(_ email: String) -> Bool {
        let emailRegEx = "^\\w+([\\.-]?\\w+)*@\\w+([\\.-]?\\w+)*(\\.\\w{2,3})+$"
        let emailPredicate = NSPredicate(format: "SELF MATCHES %@", emailRegEx)
        return emailPredicate.evaluate(with: email)
    }
}

struct EmailField: View {
    @Binding var email: String
    @State private var isValid = true

    var body: some View {
        TextField("Email", text: $email)
            .onSubmit {
                isValid = EmailValidator.isValid(email)
            }
    }
}
Note: SwiftUI does not provide built-in validation, so custom logic is required for complex validation rules.

Was this article helpful?