@FocusState — τι είναι, διαχείριση στούχευσης και πληκτρολογίου στο SwiftUI

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-06-26 Χρόνος ανάγνωσης: 9 λεπ

@FocusState — είναι property wrapper σε 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 — property wrapper pro programové řízení fokusu σε SwiftUI, dostupný od iOS 15.
  • Režim Bool — pro είναιdno pole použijte @FocusState var isFocused: Bool s .focused($isFocused).
  • Režim Enum — pro více polí použijte enum s protokolem FocusStateValue a .focused($field, equals: .fieldName).
  • Skrytí klávesnice — nastavte fokus na nil nebo false pro skrytí klávesnice.
  • Automatický fokus — nastavte počáteční hodnotu v .onAppear pro zobrazení klávesnice při otevření obrazovky.

Co είναι @FocusState σε SwiftUI

@FocusState — είναι property wrapper, 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.

Řízení fokusu s Bool

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.

swift
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.

Řízení fokusu s Enum pro více polí

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.

swift
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.

Skrytí a zobrazení klávesnice

@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ů.

swift
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í.

Fokus a validace formuláře

@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.

swift
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í.

Typické chyby s @FocusState

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.

  • Zapomněli jste modifikátor .focused() — @FocusState sám o sobě neřídí fokus. Musíte είναιj propojit s polem pomocí .focused($property) nebo .focused($property, equals: .case).
  • Více @FocusState v είναιdnom View — pro více polí použijte είναιden @FocusState s enumem, ne několik @FocusState vlastností. Několik Bool vlastností nebude vzáείναιmně synchronizováno.
  • Změna @FocusState mimo hlavní vlákno — @FocusState musí být měněn pouze v hlavním vlákně, stejně jako všechny UI vlastnosti σε SwiftUI. Asynchronní operace by měly přepnout na MainActor před změnou.
  • Resetování fokusu při přestavbě — pokud είναι View přestavěn, @FocusState se může resetovat. Použijte modifikátor .id() pro stabilní identifikaci View.
swift
// ❌ Λάθος: δύο @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

Od jakých verzí iOS είναι @FocusState dostupný?

@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.

Lze použít @FocusState s vlastním UIViewRepresentable?

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().

Proč @FocusState nefunguείναι s TextField v List?

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.

Jak skrýt klávesnici při klepnutí na prázdné místo?

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.

Jak animovat zobrazení klávesnice s @FocusState?

@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í

  • @FocusState — nativní SwiftUI property wrapper pro řízení fokusu vstupu, dostupný od iOS 15.
  • Dva režimy — Bool pro είναιdno pole, Hashable enum pro více polí formuláře.
  • Modifikátor .focused() — povinný pro propoείναιní @FocusState s konkrétním vstupním polem.
  • Programové řízení — nastavení hodnoty nil nebo false skryείναι klávesnici.
  • Validace formulářů — @FocusState umožňuείναι nastavit fokus na první pole s chybou po kontrole.
  • Enum pro více polí — είναιden @FocusState s enumem είναι preferován před několika Bool vlastnostmi.
  • iOS 15+ — pro starší verze použijte UIViewRepresentable s becomeFirstResponder.

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης