مقدمة: لماذا "التقاط" تغيير النص هو الأساس؟
\n\nتخيل: أنت تكتب تطبيقًا للبحث عن وصفات الطعام. يبدأ المستخدم في كتابة "باستا"، ويجب أن يعمل بحثك فورًا، دون الحاجة للضغط على زر. أو أنك تصمم نموذج تسجيل حيث تحتاج إلى إظهار خطأ "كلمة المرور قصيرة جدًا" فور أن يكتب المستخدم الحرف الثالث.
\n\nفي كلتا الحالتين، تحتاج إلى معرفة اللحظة الدقيقة التي يتغير فيها النص في UITextField. هذا السؤال على Stack Overflow حصد آلاف المشاهدات - وليس من دون سبب. كل مطور iOS يواجهه عاجلاً أم آجلاً.
\n\nفي عام 2025، لدينا على الأقل 4 طرق لحل هذه المشكلة. بعضها قديم ومجرب عبر الزمن. والبعض الآخر أساليب حديثة تروج لها Apple بنشاط. في هذه المقالة، سنستعرض جميع الخيارات، من الكلاسيكية إلى الحديثة، وسأوضح أي طريقة تختار لمهمة محددة.
\n\nهيا بنا! 🚀
\n\nالطريقة 1. Target-Action: طريقة تقليدية ولكنها فعالة
\n\nأبسط وأوضح طريقة، تعمل منذ iOS 2.0. نعم، عمرها أكثر من 15 عامًا، لكنها لا تزال ذات صلة.
\n\nالفكرة هي أن UITextField يرث من UIControl، وبالتالي يمكنه توليد الأحداث. نحن مهتمون بالحدث .editingChanged - يتم تشغيله مع كل تغيير في النص.
مثال على الكود (UIKit مع Storyboard أو بالكود)
\n\nimport UIKit\n\nclass ViewController: UIViewController {\n\n @IBOutlet weak var searchTextField: UITextField!\n\n override func viewDidLoad() {\n super.viewDidLoad()\n // إضافة هدف لحدث تغيير النص\n searchTextField.addTarget(self,\n action: #selector(textFieldDidChange(_:)),\n for: .editingChanged)\n }\n\n @objc func textFieldDidChange(_ textField: UITextField) {\n guard let text = textField.text else { return }\n print("النص تغير: \\(text)")\n // هنا يمكنك إجراء البحث، التحقق، إلخ.\n }\n}\n\nالإيجابيات: أقل كود، لا يتطلب الاشتراك في البروتوكولات، يعمل بسرعة.
\nالسلبيات: يجب استخدام @objc - وهو أسلوب قديم في Swift. لا يوجد تحكم دقيق (على سبيل المثال، لا يمكن التمييز بين لصق النص وحذفه).
الطريقة 2. المفوض UITextFieldDelegate: التحكم في كل حرف
\n\nإذا كنت لا تحتاج فقط إلى معرفة أن النص قد تغير، بل التأثير على التغيير (منع الإدخال، تنسيق رقم الهاتف)، فإن المفوض هو خيارك.
\n\nالطريقة الرئيسية هنا هي textField(_:shouldChangeCharactersIn:replacementString:). يتم استدعاؤها قبل أن يتغير النص فعليًا.
مثال: تنسيق رقم الهاتف
\n\nimport UIKit\n\nclass ViewController: UIViewController, UITextFieldDelegate {\n\n @IBOutlet weak var phoneTextField: UITextField!\n\n override func viewDidLoad() {\n super.viewDidLoad()\n phoneTextField.delegate = self\n }\n\n func textField(_ textField: UITextField,\n shouldChangeCharactersIn range: NSRange,\n replacementString string: String) -> Bool {\n\n // السماح فقط بالأرقام\n let allowedCharacters = CharacterSet.decimalDigits\n let characterSet = CharacterSet(charactersIn: string)\n guard allowedCharacters.isSuperset(of: characterSet) else {\n return false\n }\n\n // تحديد الطول بـ 10 أحرف\n let currentText = textField.text ?? ""\n guard let stringRange = Range(range, in: currentText) else { return false }\n let updatedText = currentText.replacingCharacters(in: stringRange, with: string)\n return updatedText.count <= 10\n }\n\n // بالإضافة: التقاط اللحظة التي تغير فيها النص بالفعل\n func textFieldDidChangeSelection(_ textField: UITextField) {\n print("النص تم تحديثه: \\(textFi