Activity 1
Build a validated profile form
Create name, email, experience-level, reminder, and start-date fields. Show useful validation and move focus between text fields.
Hint: Keep raw draft input until Save succeeds.
SwiftUI Fundamentals
Build accessible forms with native controls, validation, focus management, keyboard configuration, and clear submission behavior.
Before you begin
Learning stage
SwiftUI controls communicate both appearance and behavior to the system. Button, Toggle, Picker, TextField, SecureField, Stepper, Slider, DatePicker, and Form adapt to platform conventions, accessibility technologies, tint, keyboard input, and interaction context. Prefer a semantic control over a visual gesture attached to an arbitrary shape.
Forms should preserve user input, explain requirements, and distinguish editing from submission. Validate fields as users can act on the feedback, but avoid showing every error before interaction begins. Disable submission only when the reason is visible or obvious, and revalidate at the domain boundary.
FocusState coordinates keyboard focus without making it domain data. Configure text content type, capitalization, keyboard type, submit label, and onSubmit so the field matches its meaning. Keyboard configuration improves input but never replaces validation.
Learning stage
The form keeps raw input, derives validation, guides focus, and submits one validated value.
import SwiftUI
struct AccountForm: View {
@State private var email = ""
@State private var notificationsEnabled = true
@FocusState private var focusedField: Field?
enum Field { case email }
private var trimmedEmail: String {
email.trimmingCharacters(in: .whitespacesAndNewlines)
}
private var emailError: String? {
guard !trimmedEmail.isEmpty else { return "Email is required." }
return trimmedEmail.contains("@") ? nil : "Enter a valid email address."
}
var body: some View {
Form {
Section("Account") {
TextField("Email", text: $email)
.textContentType(.emailAddress)
.textInputAutocapitalization(.never)
.keyboardType(.emailAddress)
.focused($focusedField, equals: .email)
.submitLabel(.done)
.onSubmit(save)
if !email.isEmpty, let emailError {
Text(emailError).foregroundStyle(.red)
}
}
Toggle("Learning reminders", isOn: $notificationsEnabled)
Button("Save", action: save).disabled(emailError != nil)
}
}
private func save() {
guard emailError == nil else { focusedField = .email; return }
focusedField = nil
// Pass the validated value to the feature model.
}
}Learning stage
Connect the SwiftUI concept to complete, maintainable application features.
Learning stage
Identify patterns that weaken ownership, identity, adaptation, accessibility, or user experience.
Learning stage
Build the behavior in a small Xcode project and review it in multiple states.
Activity 1
Create name, email, experience-level, reminder, and start-date fields. Show useful validation and move focus between text fields.
Hint: Keep raw draft input until Save succeeds.
Activity 2
Find three tappable HStacks or Images in a sample screen and replace them with Button, Toggle, or NavigationLink as appropriate.
Hint: Preserve the desired appearance with styles while keeping semantic behavior.
Learning stage
Answer each question before revealing the explanation.
QUESTION 1
Button communicates action semantics and supports system interaction behavior
It integrates with accessibility, keyboard activation, roles, styles, and platform conventions.
QUESTION 2
No. It only influences the input interface; the value still requires validation.
Users can paste text and hardware keyboards are not restricted by the software keyboard layout.
Learning stage
Explain the design in terms of data flow, identity, lifecycle, platform behavior, and trade-offs.
Short answer: Keep a draft source of truth, derive validation, use semantic controls, and commit validated values at one explicit boundary.
The form owns temporary editing state and focus. Controls bind to that draft. Validation messages appear when useful, submission revalidates, and only accepted domain values are passed to the model. This protects the user's input and prevents partially valid data from leaking into application state.
Possible follow-ups
Learning stage
Good SwiftUI forms use semantic controls, preserve draft input, and create one clear validation and submission boundary. Focus and keyboard configuration improve the interaction but do not replace data rules.