@FocusState — SwiftUI-də iOS 15-də təqdim edilmiş, mətn sahələrində və digər elementlərdə daxiletmə fokusunu proqramlı idarə etməyə imkan verən property wrapper-dır. O yaranana qədər, tərtibatçılar UIKit metodlarına — becomeFirstResponder və resignFirstResponder — daxil olmaq üçün UIViewRepresentable istifadə etməli idilər. @FocusState bu problemi doğma şəkildə həll edir: xassəni .focused() modifikatoru vasitəsilə sahə ilə əlaqələndirirsiniz, bundan sonra fokusun qurulması və ya sıfırlanması sadəcə dəyər təyin etməklə baş verir. Apple Developer Documentation — FocusState (2025) məlumatına görə, @FocusState iki rejimi dəstəkləyir: sadə idarəetmə üçün Bool (fokus var və ya yox) və bir neçə sahə üçün enum, burada hər bir case müəyyən daxiletmə sahəsinə uyğun gəlir.
Başlıca
@FocusState — SwiftUI-də fokus vəziyyətini müəyyən daxiletmə sahəsi və ya digər focusable elementi ilə əlaqələndirən property wrapper-dır. UIKit-dən fərqli olaraq, burada fokusun idarə edilməsi becomeFirstResponder və resignFirstResponder metodları vasitəsilə baş verir, SwiftUI deklarativ yanaşma istifadə edir: vəziyyəti (@FocusState) elan edirsiniz və onu .focused() modifikatoru vasitəsilə elementlə əlaqələndirirsiniz. Vəziyyətin dəyişməsi avtomatik olaraq fokusu dəyişir.
@FocusState iOS 15-də ortaya çıxana qədər, tərtibatçılar UITextField ətrafında UIViewRepresentable qurmalı və ya üçüncü tərəf kitabxanalarından istifadə etməli idilər. @FocusState birbaşa SwiftUI ilə inteqrasiya olunub və TextField, TextEditor, SecureField və SearchField ilə işləyir. Bu, kodu təmizləyir, UIKit körpülərinin sayını azaldır və test edilə bilməni yaxşılaşdırır.
WWDC Session 10136 — What's new in SwiftUI (2024)-yə görə, @FocusState elementlər arasında fokus haqqında məlumat ötürmək üçün SwiftUI preference-açarlar sistemindən istifadə edir. Sahə fokus aldıqda, SwiftUI avtomatik olaraq əlaqəli @FocusState xassəsini yeniləyir ki, bu da kodda fokus dəyişikliklərinə reaksiya verməyə imkan verir.
@FocusState-dən istifadənin ən sadə yolu — Bool tipi. Sahə fokusda olduqda, xassə true dəyərinə bərabərdir. Fokus getdikdə — false. Siz true təyin etməklə fokusu məcburən qura və ya false təyin etməklə sıfırlaya bilərsiniz.
struct LoginForm: View {
@State var email = ""
@FocusState var isEmailFocused: Bool
var body: some View {
VStack {
TextField("Email", text: $email)
.focused($isEmailFocused)
Button("Klaviaturanı göstər") {
isEmailFocused = true
}
Button("Klaviaturanı gizlət") {
isEmailFocused = false
}
}
}
}
Bu nümunədə isEmailFocused istifadəçi mətn sahəsinə toxunduqda avtomatik olaraq true, klaviatura gizləndikdə isə false olur. Dümələr fokusu proqramlı idarə etməyə imkan verir — bu, xüsusi klaviaturalar, „Növbəti” dümələri və formanın göndərilməsindən sonra klaviaturanı məcburən gizlətmək lazım olduqda faydalıdır.
Bir neçə sahəli formalar üçün @FocusState FocusStateValue (və ya Hashable) protokoluna uyğun enum dəstəkləyir. Hər bir enum case müəyyən sahəyə uyğun gəlir. Bu, sahələr arasında fokus keçidinə imkan verir — məsələn, klaviaturada „Növbəti” düməsinə basıldıqda növbəti sahəyə keçmək.
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() }
}
}
}
.onSubmit modifikatoruna diqqət yetirin — o, istifadəçi klaviaturada „Return” düməsinə basdıqda çağırılır. .onSubmit daxilində focusedField-i növbəti sahəyə keçiririk, bu da avtomatik olaraq fokusu köçürür. Son sahə formanı göndərmək üçün submitForm() çağırır.
@FocusState klaviaturanı gizlətməyin sadə yolunu təmin edir — xassəni nil (enum üçün) və ya false (Bool üçün) olaraq təyin etmək kifayətdir. Bununla belə, bəzən klaviaturanı müəyyən sahəyə bağlı olmadan gizlətmək lazımdır — məsələn, boş yerə toxunduqda. Bu halda bir neçə yanaşma var.
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("Hazır") {
isFocused = false
}
}
}
}
}
placement .keyboard ilə .toolbar modifikatoru klaviaturanın üzərində dümə əlavə edir. Bu, iOS-da klaviaturanı gizlətmək üçün standart UX nümunəsidir. Alternativ yanaşma — fonə toxunduqda fokusu sıfırlamaq üçün kök VStack-də .onTapGesture istifadə etməkdir.
@FocusState formanın yoxlanması ilə əla boyda birləşir. Tipik nümunə: „Göndər” düməsinə basıldıqdan sonra bütün sahələri yoxlayın və fokusu səhv olan ilk sahəyə qurun. Bu, istifadəçi təcrübəsini yaxşılaşdırır — istifadəçi dərhal hansı sahənin düzəliş tələb etdiyini görür.
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("Göndər") { validateAndSubmit() }
}
}
func validateAndSubmit() {
if name.isEmpty {
focusedField = .name
return
}
if phone.isEmpty {
focusedField = .phone
return
}
// formanı göndər
}
}
Bu nümunədə, name sahəsi boş olduqda, fokus ona köçür və istifadəçi dərhal səhvin harada olduğunu görür. Əgər name doldurulubsa, phone yoxlanılır. Bu, formalar üçün təbii davranışdır — istifadəçi sahələri yuxarıdan aşağı doldurur və yoxlama eyni ardıcıllığa əməl edir.
Ən tez-tez rast gəlinən səhv — @FocusState-i Hashable-a uyğun olmayan tip ilə istifadə etməyə cəhd etməkdir. @FocusState xassə tipinin Hashable olmasını tələb edir (Bool və ixtiyari enum artıq uyğundur). Xüsusi struktur istifadə etməyə çalışırsınızsa, onun Hashable-ı tətbiq etdiyinə əmin olun.
// ❌ Səhv: enum əvəzinə iki @FocusState Bool
@FocusState var isNameFocused: Bool
@FocusState var isEmailFocused: Bool
// ✅ Düzgün: tək enum @FocusState
enum Field: Hashable { case name; case email }
@FocusState var focusedField: Field?
Tez-tez verilən suallar
@FocusState iOS 15, iPadOS 15, macOS 12, tvOS 15 və watchOS 8-dən mövcuddur. iOS 14 və daha köhnə versiyaları dəstəkləyən layihələr üçün UITextField və becomeFirstResponder ilə UIViewRepresentable və ya fokus idarəetməsinin xüsusi tətbiqi ilə üçüncü tərəf kitabxanalarından istifadə edin.
Bəli, bunun üçün xüsusi UIViewRepresentable-də FocusState dəstəyini UIViewRepresentable protokolu vasitəsilə tətbiq etmək lazımdır. Xüsusi view-də becomeFirstResponder və resignFirstResponder olmalıdır. SwiftUI .focused() modifikatoru göstərilərsə, @FocusState-i avtomatik olaraq bu metodlarla əlaqələndirəcək.
List və ya Form hücrələri təkrar istifadə edilə bilər ki, bu da @FocusState-in sahə ilə əlaqəsini pozur. Həll yolu: hər TextField üçün unikal identifikatorla .id() modifikatoru əlavə edin. Məsələn: .id(fieldName). Bu, SwiftUI-ni hər sahə üçün ayrı View nüsxəsi yaratmağa məcbur edir.
Kök konteynerə (VStack, ZStack) .onTapGesture əlavə edin və fokusu sıfırlayın: focusedField = nil. Bununla belə, .onTapGesture içəridəki dümƏlərə toxunuşları bloklaya bilər — .contentShape(Rectangle()) ilə konteyner və onun üzərində .onTapGesture istifadə edin, ya da xüsusi UIKitBackgroundView istifadə edin.
@FocusState klaviatura animasiyası üçün birbaşa API təmin etmir — bu, iOS-un sistem davranışıdır. Bununla belə, fokus dəyişikliklərinə .onChange(of: focusedField) və ya .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) vasitəsilə reaksiya verərək məzmunun xüsusi animasiyasını edə bilərsiniz.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun