@FocusState ist ein property wrapper in SwiftUI, der in iOS 15 eingeführt wurde und es ermöglicht, den Eingabefokus auf Textfeldern und anderen Elementen programmgesteuert zu steuern. Vor seiner Einführung mussten Entwickler UIViewRepresentable verwenden, um auf die UIKit-Methoden becomeFirstResponder und resignFirstResponder zuzugreifen. @FocusState löst dieses Problem nativ: Sie binden eine Eigenschaft über den .focused()-Modifikator an ein Feld, wonach das Setzen oder Entfernen des Fokus durch eine einfache Wertzuweisung erfolgt. Laut Apple Developer Documentation — FocusState (2025) unterstützt @FocusState zwei Modi: Bool für einfache Verwaltung (Fokus ein oder aus) und enum für mehrere Felder, wobei jeder Fall einem bestimmten Eingabefeld entspricht.
Wichtige Punkte
@FocusState ist ein property wrapper, der den Fokusstatus an ein bestimmtes Eingabefeld oder ein anderes fokussierbares Element in SwiftUI bindet. Im Gegensatz zu UIKit, wo die Fokusverwaltung über die Methoden becomeFirstResponder und resignFirstResponder erfolgt, verwendet SwiftUI einen deklarativen Ansatz: Sie deklarieren einen Status (@FocusState) und binden ihn über den .focused()-Modifikator an ein Element. Eine Änderung des Status ändert automatisch den Fokus.
Vor der Einführung von @FocusState in iOS 15 mussten Entwickler UIViewRepresentable-Wrapper um UITextField erstellen oder Bibliotheken von Drittanbietern verwenden. @FocusState ist direkt in SwiftUI integriert und funktioniert mit TextField, TextEditor, SecureField und SearchField. Dies macht den Code sauberer, reduziert die Anzahl der UIKit-Brücken und verbessert die Testbarkeit.
Laut WWDC Session 10136 — What's new in SwiftUI (2024) verwendet @FocusState das Preference-Key-System von SwiftUI, um Fokusinformationen zwischen Elementen zu übergeben. Wenn ein Feld den Fokus erhält, aktualisiert SwiftUI automatisch die zugehörige @FocusState-Eigenschaft, sodass Sie auf Fokusänderungen im Code reagieren können.
Der einfachste Weg, @FocusState zu verwenden, ist mit dem Typ Bool. Wenn ein Feld fokussiert ist, ist die Eigenschaft true. Wenn der Fokus verloren geht — false. Sie können den Fokus erzwingen, indem Sie ihn auf true setzen, oder ihn entfernen, indem Sie ihn auf false setzen.
struct LoginForm: View {
@State var email = ""
@FocusState var isEmailFocused: Bool
var body: some View {
VStack {
TextField("Email", text: $email)
.focused($isEmailFocused)
Button("Tastatur anzeigen") {
isEmailFocused = true
}
Button("Tastatur ausblenden") {
isEmailFocused = false
}
}
}
}
In diesem Beispiel wird isEmailFocused automatisch true, wenn der Benutzer auf das Textfeld tippt, und false, wenn die Tastatur ausgeblendet wird. Die Schaltflächen ermöglichen die programmgesteuerte Fokusverwaltung — nützlich für benutzerdefinierte Tastaturen, "Weiter"-Schaltflächen und Situationen, in denen Sie die Tastatur nach dem Absenden des Formulars zwangsweise ausblenden müssen.
Für Formulare mit mehreren Feldern unterstützt @FocusState ein enum, das dem FocusStateValue (oder Hashable)-Protokoll entspricht. Jeder enum-Fall entspricht einem bestimmten Feld. Dies ermöglicht das Umschalten des Fokus zwischen Feldern — zum Beispiel, wenn der Benutzer auf der Tastatur "Weiter" drückt, um zum nächsten Feld zu gelangen.
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() }
}
}
}
Beachten Sie den .onSubmit-Modifikator — er wird aufgerufen, wenn der Benutzer auf der Tastatur "Return" drückt. Innerhalb von .onSubmit schalten wir focusedField auf das nächste Feld um, was den Fokus automatisch verschiebt. Das letzte Feld ruft submitForm() zum Absenden des Formulars auf.
@FocusState bietet eine einfache Möglichkeit, die Tastatur auszublenden — setzen Sie einfach die Eigenschaft auf nil (für enum) oder false (für Bool). Manchmal müssen Sie die Tastatur jedoch ausblenden, ohne sie an ein bestimmtes Feld zu binden — zum Beispiel beim Tippen auf eine leere Stelle. In diesem Fall gibt es mehrere Ansätze.
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("Fertig") {
isFocused = false
}
}
}
}
}
Der .toolbar-Modifikator mit placement .keyboard fügt eine Schaltfläche über der Tastatur hinzu. Dies ist ein standardmäßiges UX-Muster in iOS zum Ausblenden der Tastatur. Ein alternativer Ansatz ist die Verwendung von .onTapGesture auf dem root-VStack, um den Fokus beim Tippen auf den Hintergrund zurückzusetzen.
@FocusState lässt sich hervorragend mit der Formularvalidierung kombinieren. Ein typisches Muster: Nach dem Drücken der "Senden"-Schaltfläche alle Felder validieren und den Fokus auf das erste Feld mit einem Fehler setzen. Dies verbessert die Benutzererfahrung — der Benutzer sieht sofort, welches Feld korrigiert werden muss.
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("Absenden") { validateAndSubmit() }
}
}
func validateAndSubmit() {
if name.isEmpty {
focusedField = .name
return
}
if phone.isEmpty {
focusedField = .phone
return
}
// Formular absenden
}
}
In diesem Beispiel wird, wenn das name-Feld leer ist, der Fokus darauf verschoben, und der Benutzer sieht sofort, wo der Fehler ist. Wenn name ausgefüllt ist, wird phone überprüft. Dies ist ein natürliches Verhalten für Formulare — der Benutzer füllt die Felder von oben nach unten aus, und die Validierung folgt derselben Reihenfolge.
Der häufigste Fehler ist der Versuch, @FocusState mit einem Typ zu verwenden, der nicht Hashable entspricht. @FocusState erfordert, dass der Eigenschaftstyp Hashable ist (Bool und optionale enums entsprechen bereits). Wenn Sie versuchen, eine benutzerdefinierte Struktur zu verwenden, stellen Sie sicher, dass sie Hashable implementiert.
// ❌ Falsch: zwei @FocusState Bool statt enum
@FocusState var isNameFocused: Bool
@FocusState var isEmailFocused: Bool
// ✅ Richtig: einzelnes enum @FocusState
enum Field: Hashable { case name; case email }
@FocusState var focusedField: Field?
Häufig gestellte Fragen
@FocusState ist ab iOS 15, iPadOS 15, macOS 12, tvOS 15 und watchOS 8 verfügbar. Für Projekte, die iOS 14 und älter unterstützen, verwenden Sie UIViewRepresentable mit UITextField und becomeFirstResponder oder Bibliotheken von Drittanbietern mit benutzerdefinierter Fokusverwaltungsimplementierung.
Ja, dazu müssen Sie im benutzerdefinierten UIViewRepresentable die Unterstützung für FocusState über das UIViewRepresentable-Protokoll implementieren. Die benutzerdefinierte View muss becomeFirstResponder und resignFirstResponder haben. SwiftUI verknüpft @FocusState automatisch mit diesen Methoden, wenn Sie den .focused()-Modifikator angeben.
In List oder Form können Zellen wiederverwendet werden, was die @FocusState-Bindung an das Feld unterbricht. Lösung: Fügen Sie den .id()-Modifikator mit einer eindeutigen Kennung für jedes TextField hinzu. Zum Beispiel: .id(fieldName). Dies zwingt SwiftUI, eine separate View-Instanz für jedes Feld zu erstellen.
Fügen Sie .onTapGesture zum root-Container (VStack, ZStack) hinzu und setzen Sie den Fokus zurück: focusedField = nil. Allerdings kann .onTapGesture Tippen auf innere Schaltflächen blockieren — verwenden Sie einen Container mit .contentShape(Rectangle()) und .onTapGesture darauf oder ein benutzerdefiniertes UIKitBackgroundView.
@FocusState bietet keine direkte API für die Tastaturanimation — dies ist ein iOS-Systemverhalten. Sie können jedoch mit .onChange(of: focusedField) oder .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) auf Fokusänderungen für benutzerdefinierte Content-Animationen reagieren.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch