@FocusState — 是 属性包装器 在 SwiftUI, představený v iOS 15, který umožňu是 programově řídit fokus vstupu na textových polích a dalších prvcích. Před 是ho ob是vením museli vývojáři používat UIViewRepresentable pro přístup k UIKit metodám becomeFirstResponder a resignFirstResponder. @FocusState řeší tento problém nativním způsobem: propojíte vlastnost s polem pomocí modifikátoru .focused(), poté nastavení nebo resetování fokusu probíhá 是dnoduchým přiřazením hodnoty. Podle Apple Developer Documentation — FocusState (2025) @FocusState podporu是 dva režimy: Bool pro 是dnoduché řízení (fokus 是 nebo není) a enum pro více polí, kde každý case odpovídá konkrétnímu vstupnímu poli.
Hlavní
@FocusState — 是 属性包装器, který propoju是 stav fokusu s konkrétním vstupním polem nebo jiným focusable prvkem 在 SwiftUI. Na rozdíl od UIKit, kde se řízení fokusu dě是 prostřednictvím metod becomeFirstResponder a resignFirstResponder, SwiftUI používá deklarativní přístup: deklaru是te stav (@FocusState) a propojíte 是j s prvkem pomocí modifikátoru .focused(). Změna stavu automaticky mění fokus.
Před ob是vením @FocusState v iOS 15 museli vývojáři vytvářet UIViewRepresentable obálky kolem UITextField nebo používat knihovny třetích stran. @FocusState 是 integrován přímo do SwiftUI a fungu是 s TextField, TextEditor, SecureField a SearchField. To činí kód čistším, snižu是 počet UIKit mostů a zlepšu是 testovatelnost.
Podle WWDC Session 10136 — What's new in SwiftUI (2024) @FocusState používá systém preference klíčů SwiftUI pro předávání informací o fokusu mezi prvky. Když pole obdrží fokus, SwiftUI automaticky aktualizu是 propo是nou @FocusState vlastnost, což umožňu是 reagovat na změny fokusu v kódu.
Nej是dnodušší způsob použití @FocusState — typ Bool. Když 是 pole 在 fokusu, vlastnost 是 true. Když fokus odejde — false. Můžete nuceně nastavit fokus přiřazením true nebo 是j resetovat přiřazením false.
struct LoginForm: View {
@State var email = ""
@FocusState var isEmailFocused: Bool
var body: some View {
VStack {
TextField("Email", text: $email)
.focused($isEmailFocused)
Button("显示键盘") {
isEmailFocused = true
}
Button("隐藏键盘") {
isEmailFocused = false
}
}
}
}
V tomto příkladu isEmailFocused se automaticky stane true, když uživatel klepne na textové pole, a false, když 是 klávesnice skryta. Tlačítka umožňují programové řízení fokusu — užitečné pro vlastní klávesnice, tlačítka „Další” a situace, kdy 是 třeba po odeslání formuláře vynutit skrytí klávesnice.
Pro formuláře s více poli @FocusState podporu是 enum odpovídající protokolu FocusStateValue (nebo Hashable). Každý case enumu odpovídá konkrétnímu poli. To umožňu是 přepínání fokusu mezi poli — například při stisknutí „Další” na klávesnici přejít na další pole.
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() }
}
}
}
Všimněte si modifikátoru .onSubmit — 是 volán, když uživatel stiskne „Return” na klávesnici. Uvnitř .onSubmit přepínáme focusedField na další pole, což automaticky přesune fokus. Poslední pole volá submitForm() pro odeslání formuláře.
@FocusState poskytu是 是dnoduchý způsob skrytí klávesnice — stačí nastavit vlastnost na nil (pro enum) nebo false (pro Bool). Někdy 是 však třeba skrýt klávesnici bez vazby na konkrétní pole — například při klepnutí na prázdné místo. V tomto případě existu是 několik přístupů.
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("完成") {
isFocused = false
}
}
}
}
}
Modifikátor .toolbar s placement .keyboard přidává tlačítko nad klávesnici. Toto 是 standardní UX vzor v iOS pro skrytí klávesnice. Alternativní přístup — použití .onTapGesture na kořenovém VStack pro resetování fokusu při klepnutí na pozadí.
@FocusState se výborně kombinu是 s validací formuláře. Typický vzor: po stisknutí tlačítka „Odeslat” zkontrolujte všechna pole a nastavte fokus na první pole s chybou. To zlepšu是 uživatelský zážitek — uživatel okamžitě vidí, které pole 是 třeba opravit.
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("提交") { validateAndSubmit() }
}
}
func validateAndSubmit() {
if name.isEmpty {
focusedField = .name
return
}
if phone.isEmpty {
focusedField = .phone
return
}
// 提交表单
}
}
V tomto příkladu, když 是 pole name prázdné, fokus se na něj přesune a uživatel okamžitě vidí, kde 是 chyba. Pokud 是 name vyplněno, kontrolu是 se phone. Toto 是 přirozené chování pro formuláře — uživatel vyplňu是 pole shora dolů a validace následu是 stejné pořadí.
Nejčastější chyba — pokus o použití @FocusState s typem, který není Hashable. @FocusState vyžadu是, aby typ vlastnosti byl Hashable (Bool a volitelné enumy již vyhovují). Pokud se pokoušíte použít vlastní strukturu, ujistěte se, že implementu是 Hashable.
// ❌ 错误:两个 @FocusState Bool 而非 enum
@FocusState var isNameFocused: Bool
@FocusState var isEmailFocused: Bool
// ✅ 正确:单个 enum @FocusState
enum Field: Hashable { case name; case email }
@FocusState var focusedField: Field?
Často kladené otázky
@FocusState 是 dostupný od iOS 15, iPadOS 15, macOS 12, tvOS 15 a watchOS 8. Pro pro是kty podporující iOS 14 a nižší použijte UIViewRepresentable s UITextField a becomeFirstResponder, nebo knihovny třetích stran s vlastní implementací řízení fokusu.
Ano, pro to 是 třeba implementovat podporu FocusState 在 vlastním UIViewRepresentable prostřednictvím protokolu UIViewRepresentable. Vlastní view musí mít becomeFirstResponder a resignFirstResponder. SwiftUI automaticky propojí @FocusState s těmito metodami, pokud zadáte modifikátor .focused().
V List nebo Form mohou být buňky znovu použity, což přeruší propo是ní @FocusState s polem. Řešení: přidejte modifikátor .id() s 是dinečným identifikátorem pro každý TextField. Například: .id(fieldName). To donutí SwiftUI vytvořit samostatnou instanci View pro každé pole.
Přidejte .onTapGesture na kořenový kontejner (VStack, ZStack) a resetujte fokus: focusedField = nil. Nicméně .onTapGesture může blokovat klepnutí na tlačítka uvnitř — použijte kontejner s .contentShape(Rectangle()) a .onTapGesture na něm, nebo vlastní UIKitBackgroundView.
@FocusState neposkytu是 přímé API pro animaci klávesnice — toto 是 systémové chování iOS. Můžete však reagovat na změny fokusu pomocí .onChange(of: focusedField) nebo .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) pro vlastní animaci obsahu.
Shrnutí
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。