@FocusState — is een property wrapper in SwiftUI, geïntroduceerd in iOS 15, waarmee u programmatisch de invoerfocus op tekstvelden en andere elementen kunt beheren. Voordat het verscheen, moesten ontwikkelaars UIViewRepresentable gebruiken om toegang te krijgen tot de UIKit-methoden becomeFirstResponder en resignFirstResponder. @FocusState lost dit probleem op een native manier op: u koppelt een eigenschap aan het veld via de .focused()-modifier, waarna het instellen of resetten van de focus plaatsvindt door simpelweg een waarde toe te wijzen. Volgens Apple Developer Documentation — FocusState (2025) ondersteunt @FocusState twee modi: Bool voor eenvoudig beheer (focus is er of niet) en enum voor meerdere velden, waarbij elke case overeenkomt met een specifiek invoerveld.
Belangrijkste
@FocusState — is een property wrapper die de focusstatus koppelt aan een specifiek invoerveld of een ander focusbaar element in SwiftUI. In tegenstelling tot UIKit, waar focusbeheer plaatsvindt via de methoden becomeFirstResponder en resignFirstResponder, gebruikt SwiftUI een declaratieve benadering: u declareert de status (@FocusState) en koppelt deze aan het element via de .focused()-modifier. Het wijzigen van de status verandert automatisch de focus.
Voordat @FocusState in iOS 15 verscheen, moesten ontwikkelaars UIViewRepresentable-wrappers rond UITextField maken of bibliotheken van derden gebruiken. @FocusState is direct geïntegreerd in SwiftUI en werkt met TextField, TextEditor, SecureField en SearchField. Dit maakt de code schoner, vermindert het aantal UIKit-bruggen en verbetert de testbaarheid.
Volgens WWDC Session 10136 — What's new in SwiftUI (2024) gebruikt @FocusState het SwiftUI-preference-sleutelsysteem om focusinformatie tussen elementen door te geven. Wanneer een veld focus ontvangt, werkt SwiftUI automatisch de gekoppelde @FocusState-eigenschap bij, waardoor u kunt reageren op focuswijzigingen in de code.
De eenvoudigste manier om @FocusState te gebruiken — het type Bool. Wanneer het veld in focus is, is de eigenschap true. Wanneer de focus verdwijnt — false. U kunt de focus geforceerd instellen door true toe te wijzen of resetten door false toe te wijzen.
struct LoginForm: View {
@State var email = ""
@FocusState var isEmailFocused: Bool
var body: some View {
VStack {
TextField("Email", text: $email)
.focused($isEmailFocused)
Button("Toetsenbord tonen") {
isEmailFocused = true
}
Button("Toetsenbord verbergen") {
isEmailFocused = false
}
}
}
}
In dit voorbeeld wordt isEmailFocused automatisch true wanneer de gebruiker op het tekstveld tikt, en false wanneer het toetsenbord wordt verborgen. Knoppen maken programmatisch focusbeheer mogelijk — handig voor aangepaste toetsenborden, „Volgende”-knoppen en situaties waarin het toetsenbord na het verzenden van een formulier geforceerd moet worden verborgen.
Voor formulieren met meerdere velden ondersteunt @FocusState een enum die voldoet aan het FocusStateValue-protocol (of Hashable). Elke case van de enum komt overeen met een specifiek veld. Hiermee kunt u de focus tussen velden schakelen — bijvoorbeeld door op „Volgende” op het toetsenbord te drukken om naar het volgende veld te gaan.
struct RegistrationForm: View {
enum Field: Hashable {
case email
case password
case confirmPassword
}
@State var email = ""
@State var password = ""
@State var confirmPassword = ""
@FocusState var focusedField: Field?
var body: some View {
Form {
TextField("Email", text: $email)
.focused($focusedField, equals: .email)
.onSubmit { focusedField = .password }
SecureField("Password", text: $password)
.focused($focusedField, equals: .password)
.onSubmit { focusedField = .confirmPassword }
SecureField("Confirm", text: $confirmPassword)
.focused($focusedField, equals: .confirmPassword)
.onSubmit { submitForm() }
}
}
}
Let op de .onSubmit-modifier — deze wordt aangeroepen wanneer de gebruiker op „Return” op het toetsenbord drukt. Binnen .onSubmit schakelen we focusedField naar het volgende veld, wat automatisch de focus verplaatst. Het laatste veld roept submitForm() aan om het formulier te verzenden.
@FocusState biedt een eenvoudige manier om het toetsenbord te verbergen — stel de eigenschap in op nil (voor enum) of false (voor Bool). Soms moet u echter het toetsenbord verbergen zonder koppeling aan een specifiek veld — bijvoorbeeld bij het tikken op een lege plek. In dit geval zijn er verschillende benaderingen.
struct DismissKeyboardView: View {
@State var text = ""
@FocusState var isFocused: Bool
var body: some View {
TextField("Enter text", text: $text)
.focused($isFocused)
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
Spacer()
Button("Gereed") {
isFocused = false
}
}
}
}
}
De .toolbar-modifier met placement .keyboard voegt een knop boven het toetsenbord toe. Dit is een standaard UX-patroon in iOS om het toetsenbord te verbergen. Een alternatieve benadering — gebruik .onTapGesture op de root-VStack om de focus te resetten bij het tikken op de achtergrond.
@FocusState combineert uitstekend met formuliervalidatie. Het typische patroon: na het indrukken van de knop „Verzenden” controleert u alle velden en stelt u de focus in op het eerste veld met een fout. Dit verbetert de gebruikerservaring — de gebruiker ziet direct welk veld moet worden gecorrigeerd.
struct ValidatedForm: View {
enum Field: Hashable { case name; case phone }
@State var name = ""
@State var phone = ""
@FocusState var focusedField: Field?
@State var errors: [String] = []
var body: some View {
Form {
TextField("Name", text: $name)
.focused($focusedField, equals: .name)
TextField("Phone", text: $phone)
.focused($focusedField, equals: .phone)
Button("Verzenden") { validateAndSubmit() }
}
}
func validateAndSubmit() {
if name.isEmpty {
focusedField = .name
return
}
if phone.isEmpty {
focusedField = .phone
return
}
// formulier verzenden
}
}
In dit voorbeeld, wanneer het veld name leeg is, verplaatst de focus zich ernaar en ziet de gebruiker direct waar de fout zit. Als name is ingevuld, wordt phone gecontroleerd. Dit is natuurlijk gedrag voor formulieren — de gebruiker vult velden van boven naar beneden in en de validatie volgt dezelfde volgorde.
De meest voorkomende fout — proberen @FocusState te gebruiken met een type dat niet voldoet aan Hashable. @FocusState vereist dat het type van de eigenschap Hashable is (Bool en optionele enum voldoen al). Als u een aangepaste structuur probeert te gebruiken, zorg er dan voor dat deze Hashable implementeert.
// ❌ Fout: twee @FocusState Bool in plaats van enum
@FocusState var isNameFocused: Bool
@FocusState var isEmailFocused: Bool
// ✅ Juist: één enum @FocusState
enum Field: Hashable { case name; case email }
@FocusState var focusedField: Field?
Veelgestelde vragen
@FocusState is beschikbaar vanaf iOS 15, iPadOS 15, macOS 12, tvOS 15 en watchOS 8. Voor projecten die iOS 14 en lager ondersteunen, gebruikt u UIViewRepresentable met UITextField en becomeFirstResponder, of bibliotheken van derden met een aangepaste implementatie van focusbeheer.
Ja, hiervoor moet u in de aangepaste UIViewRepresentable ondersteuning voor FocusState implementeren via het UIViewRepresentable-protocol. De aangepaste view moet becomeFirstResponder en resignFirstResponder hebben. SwiftUI koppelt @FocusState automatisch aan deze methoden als u de .focused()-modifier opgeeft.
In List of Form kunnen cellen worden hergebruikt, wat de koppeling van @FocusState met het veld verbreekt. Oplossing: voeg de .id()-modifier met een unieke identificatie toe voor elke TextField. Bijvoorbeeld: .id(fieldName). Dit dwingt SwiftUI om een afzonderlijke View-instantie voor elk veld te maken.
Voeg .onTapGesture toe aan de root-container (VStack, ZStack) en reset de focus: focusedField = nil. Echter, .onTapGesture kan tikken op knoppen binnenin blokkeren — gebruik een container met .contentShape(Rectangle()) en .onTapGesture erop, of een aangepaste UIKitBackgroundView.
@FocusState biedt geen directe API voor toetsenbordanimatie — dit is systeemgedrag van iOS. U kunt echter reageren op focuswijzigingen met .onChange(of: focusedField) of .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) voor aangepaste animatie van de inhoud.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook