@FocusState SwiftUI میں ایک property wrapper ہے، جو iOS 15 میں متعارف کرایا گیا، جو آپ کو ٹیکسٹ فیلڈز اور دیگر عناصر پر ان پٹ فوکس کو پروگرامی طور پر کنٹرول کرنے کی اجازت دیتا ہے۔ اس کے آنے سے پہلے، ڈویلپرز کو becomeFirstResponder اور resignFirstResponder جیسے UIKit طریقوں تک رسائی کے لیے UIViewRepresentable استعمال کرنا پڑتا تھا۔ @FocusState اس مسئلے کو مقامی طور پر حل کرتا ہے: آپ .focused() موڈیفائر کے ذریعے ایک پراپرٹی کو فیلڈ سے باندھتے ہیں، جس کے بعد فوکس سیٹ یا ہٹانا ایک سادہ ویلیو اسائنمنٹ سے ہوتا ہے۔ Apple Developer Documentation — FocusState (2025) کے مطابق، @FocusState دو موڈ کو سپورٹ کرتا ہے: سادہ انتظام کے لیے Bool (فوکس آن یا آف) اور متعدد فیلڈز کے لیے enum، جہاں ہر case ایک مخصوص ان پٹ فیلڈ سے مطابقت رکھتا ہے۔
اہم نکات
@FocusState ایک property wrapper ہے جو فوکس کی حالت کو SwiftUI میں ایک مخصوص ان پٹ فیلڈ یا دیگر فوکس ایبل عنصر سے باندھتا ہے۔ UIKit کے برعکس، جہاں فوکس کا انتظام becomeFirstResponder اور resignFirstResponder طریقوں کے ذریعے ہوتا ہے، SwiftUI ایک اعلانیہ طریقہ استعمال کرتا ہے: آپ ایک حالت (@FocusState) کا اعلان کرتے ہیں اور اسے .focused() موڈیفائر کے ذریعے ایک عنصر سے باندھتے ہیں۔ حالت تبدیل کرنے سے خود بخود فوکس تبدیل ہو جاتا ہے۔
iOS 15 میں @FocusState کے متعارف ہونے سے پہلے، ڈویلپرز کو UITextField کے ارد گرد UIViewRepresentable ریپر بنانے یا تھرڈ پارٹی لائبریریاں استعمال کرنی پڑتی تھیں۔ @FocusState براہ راست SwiftUI میں ضم ہے اور TextField، TextEditor، SecureField اور SearchField کے ساتھ کام کرتا ہے۔ یہ کوڈ کو صاف ستھرا بناتا ہے، UIKit پلوں کی تعداد کم کرتا ہے اور جانچ کی صلاحیت کو بہتر بناتا ہے۔
WWDC Session 10136 — What's new in SwiftUI (2024) کے مطابق، @FocusState عناصر کے درمیان فوکس کی معلومات منتقل کرنے کے لیے SwiftUI کے preference key سسٹم کا استعمال کرتا ہے۔ جب کوئی فیلڈ فوکس حاصل کرتا ہے، SwiftUI خود بخود متعلقہ @FocusState پراپرٹی کو اپ ڈیٹ کرتا ہے، جس سے آپ کوڈ میں فوکس تبدیلیوں پر ردعمل دے سکتے ہیں۔
@FocusState استعمال کرنے کا سب سے آسان طریقہ Bool قسم کے ساتھ ہے۔ جب کوئی فیلڈ فوکس میں ہوتی ہے، پراپرٹی true ہوتی ہے۔ جب فوکس ختم ہو جاتا ہے — false۔ آپ اسے true پر سیٹ کر کے فوکس مجبور کر سکتے ہیں، یا 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
}
}
}
}
اس مثال میں، isEmailFocused خود بخود true ہو جاتا ہے جب صارف ٹیکسٹ فیلڈ پر ٹیپ کرتا ہے، اور false جب کی بورڈ چھپ جاتا ہے۔ بٹن آپ کو پروگرامی طور پر فوکس منظم کرنے کی اجازت دیتے ہیں — کسٹم کی بورڈز، "اگلا" بٹن، اور ان حالات کے لیے مفید جہاں آپ کو فارم جمع کروانے کے بعد زبردستی کی بورڈ چھپانے کی ضرورت ہوتی ہے۔
متعدد فیلڈز والے فارم کے لیے، @FocusState FocusStateValue (یا Hashable) پروٹوکول کی پیروی کرنے والے enum کو سپورٹ کرتا ہے۔ ہر enum case ایک مخصوص فیلڈ سے مطابقت رکھتا ہے۔ یہ فیلڈز کے درمیان فوکس تبدیل کرنے کی اجازت دیتا ہے — مثال کے طور پر، جب صارف اگلے فیلڈ میں جانے کے لیے کی بورڈ پر "اگلا" دباتا ہے۔
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 موڈیفائر پر غور کریں — یہ اس وقت کال ہوتا ہے جب صارف کی بورڈ پر "Return" دباتا ہے۔ .onSubmit کے اندر ہم focusedField کو اگلے فیلڈ پر سوئچ کرتے ہیں، جو خود بخود فوکس منتقل کر دیتا ہے۔ آخری فیلڈ فارم جمع کروانے کے لیے submitForm() کو کال کرتا ہے۔
@FocusState کی بورڈ چھپانے کا ایک آسان طریقہ فراہم کرتا ہے — بس پراپرٹی کو nil (enum کے لیے) یا false (Bool کے لیے) پر سیٹ کریں۔ تاہم، بعض اوقات آپ کو کی بورڈ کو کسی مخصوص فیلڈ سے باندھے بغیر چھپانے کی ضرورت ہوتی ہے — مثال کے طور پر، خالی جگہ پر ٹیپ کرتے وقت۔ اس صورت میں، کئی طریقے ہیں۔
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
}
}
}
}
}
placement .keyboard کے ساتھ .toolbar موڈیفائر کی بورڈ کے اوپر ایک بٹن شامل کرتا ہے۔ کی بورڈ چھپانے کے لیے iOS میں یہ ایک معیاری UX پیٹرن ہے۔ ایک متبادل طریقہ پس منظر پر ٹیپ کرنے پر فوکس ری سیٹ کرنے کے لیے روٹ VStack پر .onTapGesture استعمال کرنا ہے۔
@FocusState فارم کی توثیق کے ساتھ بہترین طور پر مل جاتا ہے۔ ایک عام پیٹرن: "جمع کروائیں" بٹن دبانے کے بعد، تمام فیلڈز کی توثیق کریں اور پہلی غلطی والے فیلڈ پر فوکس سیٹ کریں۔ یہ صارف کے تجربے کو بہتر بناتا ہے — صارف فوراً دیکھ لیتا ہے کہ کس فیلڈ کو درست کرنے کی ضرورت ہے۔
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
}
// فارم جمع کروائیں
}
}
اس مثال میں، اگر name فیلڈ خالی ہے، تو فوکس اس کی طرف چلا جاتا ہے، اور صارف فوراً دیکھ لیتا ہے کہ غلطی کہاں ہے۔ اگر name بھرا ہوا ہے، تو phone چیک کیا جاتا ہے۔ یہ فارموں کے لیے قدرتی رویہ ہے — صارف اوپر سے نیچے فیلڈز بھرتا ہے، اور توثیق اسی ترتیب کی پیروی کرتی ہے۔
سب سے عام غلطی Hashable کی پیروی نہ کرنے والی قسم کے ساتھ @FocusState استعمال کرنے کی کوشش کرنا ہے۔ @FocusState کے لیے ضروری ہے کہ پراپرٹی کی قسم Hashable ہو (Bool اور اختیاری enum پہلے ہی پیروی کرتے ہیں)۔ اگر آپ کسٹم سٹرکچر استعمال کرنے کی کوشش کر رہے ہیں، تو یقینی بنائیں کہ یہ Hashable کو لاگو کرتا ہے۔
// ❌ غلط: enum کے بجائے دو @FocusState Bool
@FocusState var isNameFocused: Bool
@FocusState var isEmailFocused: Bool
// ✅ صحیح: ایک enum @FocusState
enum Field: Hashable { case name; case email }
@FocusState var focusedField: Field?
اکثر پوچھے گئے سوالات
@FocusState iOS 15، iPadOS 15، macOS 12، tvOS 15 اور watchOS 8 سے دستیاب ہے۔ iOS 14 اور اس سے نیچے کو سپورٹ کرنے والے پروجیکٹس کے لیے، UITextField اور becomeFirstResponder کے ساتھ UIViewRepresentable استعمال کریں، یا کسٹم فوکس انتظام کے نفاذ کے ساتھ تھرڈ پارٹی لائبریریاں استعمال کریں۔
ہاں، اس کے لیے کسٹم UIViewRepresentable میں UIViewRepresentable پروٹوکول کے ذریعے FocusState سپورٹ کو لاگو کرنا ہوگا۔ کسٹم View میں becomeFirstResponder اور resignFirstResponder ہونا ضروری ہے۔ اگر آپ .focused() موڈیفائر بتاتے ہیں تو SwiftUI خود بخود @FocusState کو ان طریقوں سے جوڑ دے گا۔
List یا Form میں، سیلز دوبارہ استعمال ہو سکتے ہیں، جو فیلڈ کے ساتھ @FocusState بائنڈنگ کو توڑ دیتا ہے۔ حل: ہر TextField کے لیے ایک منفرد شناخت کنندہ کے ساتھ .id() موڈیفائر شامل کریں۔ مثال کے طور پر: .id(fieldName)۔ یہ SwiftUI کو ہر فیلڈ کے لیے ایک علیحدہ View مثال بنانے پر مجبور کرتا ہے۔
روٹ کنٹینر (VStack, ZStack) پر .onTapGesture شامل کریں اور فوکس ری سیٹ کریں: focusedField = nil۔ تاہم، .onTapGesture اندر کے بٹنوں پر ٹیپ کو روک سکتا ہے — .contentShape(Rectangle()) کے ساتھ کنٹینر اور اس پر .onTapGesture استعمال کریں، یا کسٹم UIKitBackgroundView استعمال کریں۔
@FocusState کی بورڈ اینی میشن کے لیے براہ راست API فراہم نہیں کرتا — یہ iOS سسٹم کا رویہ ہے۔ تاہم، آپ کسٹم مواد کی اینی میشن کے لیے .onChange(of: focusedField) یا .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) کے ساتھ فوکس تبدیلیوں پر ردعمل دے سکتے ہیں۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں