التحقق من النموذج في SwiftUI بشعور محلي: التركيز والأخطاء
التحقق من النماذج في SwiftUI بطريقة تشعر أنها محلية: إدارة التركيز، عرض الأخطاء داخل الحقول في الوقت المناسب، وإظهار رسائل الخادم بوضوح دون إزعاج المستخدمين.

كيف يبدو التحقق "بشعور محلي" في SwiftUI
نموذج iOS الذي يشعر بأنه «محلي» هادئ. لا يتجادل مع المستخدم أثناء الكتابة. يعطي ملاحظات واضحة عندما تكون مهمة، ولا يجعلك تبحث عما حدث خطأ.
التوقع الأساسي هو القابلية للتنبؤ. نفس الأفعال يجب أن تؤدي إلى نفس النوع من الملاحظات في كل مرة. إذا كان الحقل غير صالح، يجب أن يظهر ذلك في مكان ثابت، وبنبرة متسقة، ومع خطوة تالية واضحة.
تحتاج معظم النماذج عادةً إلى ثلاثة أنواع من القواعد:
- قواعد الحقل: هل هذه القيمة الفردية صالحة (فارغة، التنسيق، الطول)؟
- قواعد عبر الحقول: هل القيم متطابقة أو تعتمد على بعضها البعض (كلمة المرور وتأكيدها)؟
- قواعد الخادم: هل يقبلها الخادم (البريد مستخدم بالفعل، يتطلب دعوة)؟
التوقيت أهم من الصياغة الذكية. التحقق الجيد ينتظر لحظة ذات مغزى، ثم يتحدث مرة واحدة وبوضوح. إيقاع عملي يبدو هكذا:
- أبقِ الصمت أثناء كتابة المستخدم، خصوصًا لقواعد التنسيق.
- أظهر الملاحظات بعد مغادرة الحقل، أو بعد أن ينقر المستخدم زر الإرسال.
- اجعل الأخطاء مرئية حتى تُصلح، ثم قم بإزالتها فورًا.
يجب أن يكون التحقق صامتًا بينما لا يزال المستخدم يشكل الإجابة، مثل كتابة بريد إلكتروني أو كلمة مرور. إظهار خطأ على الحرف الأول يشعر بالملاحقة، حتى لو كان صحيحًا تقنيًا.
يجب أن يصبح التحقق مرئيًا عندما يُشير المستخدم إلى أنه انتهى: انتقل التركيز، أو حاول الإرسال. هذه هي اللحظة التي يريدون فيها توجيهًا، ويمكنك حينها مساعدتهم على الوصول للحقل الذي يحتاج انتباهاً.
اضبط التوقيت جيدًا وسيصبح كل شيء أسهل. يمكن أن تبقى الرسائل الخطية قصيرة، يحسّس تحويل التركيز بالمساعدة، وتشعر أخطاء الخادم كملاحظات طبيعية بدلًا من معاقبة.
إعداد نموذج حالة تحقق بسيط
النموذج الذي يشعر بأنه محلي يبدأ بفصل واضح: النص الذي كتبه المستخدم ليس نفس رأي التطبيق عن ذلك النص. إذا خلطت بينهما، ستظهر الأخطاء مبكرًا جدًا أو ستفقد رسائل الخادم عندما تحدّث الواجهة.
نهج بسيط هو إعطاء كل حقل حالة خاصة مكوّنة من أربعة أجزاء: القيمة الحالية، ما إذا كان المستخدم قد تفاعل معها، الخطأ المحلي (على الجهاز)، وخطأ الخادم (إن وجد). ثم يمكن لواجهة المستخدم أن تقرر ما الذي تعرضه بناءً على "مُلمَس" و"محاولات الإرسال" بدلًا من الرد على كل ضغطة مفتاح.
struct FieldState {
var value: String = ""
var touched: Bool = false
var localError: String? = nil
var serverError: String? = nil
// One source of truth for what the UI displays
func displayedError(submitted: Bool) -> String? {
guard touched || submitted else { return nil }
return localError ?? serverError
}
}
struct FormState {
var submitted: Bool = false
var email = FieldState()
var password = FieldState()
}
بعض القواعد الصغيرة تحافظ على قابلية التنبؤ:
- حافظ على فصل الأخطاء المحلية وخطأ الخادم. القواعد المحلية (مثل "مطلوب" أو "بريد غير صالح") لا ينبغي أن تكتب فوق رسالة الخادم مثل "البريد مستخدم بالفعل".
- قم بمسح
serverErrorعندما يُحرر المستخدم ذلك الحقل مرة أخرى، حتى لا يبقى ينظر إلى رسالة قديمة. - اجعل
touched = trueفقط عندما يترك المستخدم الحقل (أو عندما تقرر أنه حاول التفاعل)، وليس عند الحرف الأول المكتوب.
مع هذا النمط، يمكن لعرضك أن يربط إلى value بحرية. التحقق يحدث في localError، وطبقة الـ API تضع serverError، دون أن يتصارعا.
معالجة التركيز التي توجه ولا تزعج
يجب أن يشعر التحقق في SwiftUI أن لوحة المفاتيح تساعد المستخدم على إتمام المهمة، لا أن التطبيق يوبّخه. التركيز جزء كبير من ذلك.
نمط بسيط هو التعامل مع التركيز كمصدر واحد للحقائق باستخدام @FocusState. عرّف enum لحقولك، اربط كل حقل به، ثم انتقل للأمام عندما يضغط المستخدم زر لوحة المفاتيح.
enum Field: Hashable { case email, password, confirm }
@FocusState private var focused: Field?
TextField("Email", text: $email)
.textContentType(.emailAddress)
.keyboardType(.emailAddress)
.textInputAutocapitalization(.never)
.submitLabel(.next)
.focused($focused, equals: .email)
.onSubmit { focused = .password }
SecureField("Password", text: $password)
.submitLabel(.next)
.focused($focused, equals: .password)
.onSubmit { focused = .confirm }
ما يحافظ على هذا الإحساس المحلي هو ضبط النفس. حرك التركيز فقط بعد إجراءات واضحة من المستخدم: النقر على Next أو Done أو الزر الرئيسي. عند الإرسال، ضع التركيز على أول حقل غير صالح (وامرر العرض إليه إذا لزم). لا تسرق التركيز بينما المستخدم يكتب، حتى لو كانت القيمة غير صالحة حاليًا. كما كن متسقًا في تسمية أزرار لوحة المفاتيح: Next للحقول الوسيطة، Done للحقل الأخير.
مثال شائع هو صفحة الاشتراك. المستخدم ينقر "إنشاء حساب". تتحقق مرة، تظهر الأخطاء، ثم تضع التركيز على أول حقل فشل (غالبًا البريد). إذا كانوا في حقل كلمة المرور وما زالوا يكتبون، لا تقفز بهم إلى البريد أثناء الكتابة. هذه التفاصيل الصغيرة غالبًا ما تفرق بين "نموذج iOS مصقول" و"نموذج مزعج".
الأخطاء المضمّنة التي تظهر في الوقت المناسب
يجب أن تشعر الأخطاء المضمّنة كنصيحة هادئة، لا توبيخ. الاختلاف الأكبر بين "محلي" و"مزعج" هو توقيت عرض الرسالة.
قواعد التوقيت
إذا ظهر الخطأ بمجرد أن يبدأ شخص ما في الكتابة، فإنه يقطع الانتباه. قاعدة أفضل هي: انتظر حتى يحصل المستخدم على فرصة عادلة لإكمال الحقل.
أوقات مناسبة لإظهار خطأ مضمّن:
- بعد فقدان الحقل للتركيز
- بعد أن ينقر المستخدم زر الإرسال
- بعد توقف قصير أثناء الكتابة (فقط لفحوصات واضحة، مثل تنسيق البريد)
نهج موثوق هو إظهار الرسالة فقط عندما يكون الحقل ملموسًا أو عندما تم محاولة الإرسال. النموذج الجديد يظل هادئًا، لكن المستخدم يحصل على إرشادات واضحة بمجرد تفاعله.
التخطيط والأسلوب
لا شيء يبدو أقل شبهاً بـ iOS من تخبط التخطيط عندما تظهر رسالة خطأ. احجز مساحة للرسالة، أو أنمّ ظهورها حتى لا تدفع الحقل التالي فجأة للأسفل.
اجعل نص الخطأ قصيرًا ومحددًا، مع إصلاح واحد لكل رسالة. "يجب أن تكون كلمة المرور على الأقل 8 أحرف" قابلة للتنفيذ. "إدخال غير صالح" ليست كذلك.
من ناحية الأسلوب، استهدف البساطة والاتساق. خط صغير تحت الحقل (مثل footnote)، لون خطأ موحد، وتسليط لطيف على الحقل عادةً ما يقرأ أفضل من خلفيات ثقيلة. أزل الرسالة بمجرد أن تصبح القيمة صالحة.
مثال واقعي: في نموذج التسجيل، لا تظهر "البريد غير صالح" بينما المستخدم لا يزال يكتب name@. أظهرها بعد مغادرة الحقل، أو بعد توقف بسيط، وأزلها مع لحظة صلاحية العنوان.
تدفق التحقق المحلي: الكتابة، مغادرة الحقل، الإرسال
لدى التدفق المحلي الجيد ثلاث سرعات: تلميحات لطيفة أثناء الكتابة، فحوصات أشد عند مغادرة الحقل، وقواعد كاملة عند الإرسال. هذا الإيقاع يجعل التحقق يبدو محليًا.
أثناء كتابة المستخدم، اجعل التحقق خفيفًا وهادئًا. فكّر بـ "هل هذا مستحيل بوضوح؟" لا "هل هذا مثالي؟" لحقل البريد، قد تتحقق فقط من وجود @ وعدم وجود مسافات. لكلمة المرور، قد تعرض مساعدًا صغيرًا مثل "8+ أحرف" بمجرد أن يبدأوا في الكتابة، لكن تجنب الأخطاء الحمراء على أول ضغطة.
عند مغادرة الحقل، شغّل قواعد أعنف لحقل واحد وأظهر الأخطاء المضمّنة إن لزم. هنا تنتمي قواعد "مطلوب" و"تنسيق غير صالح". كما أنها لحظة جيدة لقص المسافات وتطبيع المدخل (مثل تحويل البريد لحروف صغيرة) حتى يرى المستخدم ما سيرسل بالفعل.
عند الإرسال، تحقق من كل شيء مرة أخرى، بما في ذلك قواعد عبر الحقول التي لا يمكنك تقريرها مبكرًا. المثال الكلاسيكي هو تطابق كلمة المرور وتأكيدها. إذا فشل هذا، ضع التركيز على الحقل الذي يحتاج إصلاحًا وأظهر رسالة واضحة بجانبه.
استخدم زر الإرسال بعناية. اتركه ممكّنًا أثناء ملء المستخدم للنموذج. عطّله فقط عندما يكون النقر بلا تأثير (مثلاً أثناء الإرسال بالفعل). إذا عطّلته لحالة غير صالحة، فاظهر ما يجب إصلاحه بجانبه.
أثناء الإرسال، أظهر حالة تحميل واضحة. استبدل تسمية الزر بـ ProgressView، امنع النقرات المكررة، وأبقِ النموذج مرئيًا لكي يفهم المستخدم ما يحدث. إذا استغرق الطلب أكثر من ثانية، تسمية قصيرة مثل "إنشاء الحساب..." تقلل القلق دون إضافة ضوضاء.
تحقق من جهة الخادم دون إزعاج المستخدمين
فحوصات الخادم هي المصدر النهائي للحقيقة، حتى لو كانت الفحوصات المحلية قوية. قد تجتاز كلمة المرور قواعدك لكنها تفشل لأنها شائعة جدًا، أو قد يكون البريد مستخدمًا بالفعل.
أكبر تحسين في تجربة المستخدم هو فصل "إدخالك غير مقبول" عن "لم نتمكن من الوصول إلى الخادم". إذا انتهت الجلسة أو المستخدم غير متصل، لا تجعل الحقول غير صالحة. أظهر شريطًا هادئًا أو تنبيهًا مثل "تعذر الاتصال. حاول مرة أخرى." واحتفظ بالنموذج كما هو.
عندما يقول الخادم إن التحقق فشل، احتفظ بمدخلات المستخدم كما هي وأشر إلى الحقول المحددة. مسح النموذج، أو مسح كلمة المرور، أو نقل التركيز بعيدًا يجعل الناس يشعرون أنهم عوقبوا لمحاولتهم.
نمط بسيط هو تحليل استجابة الخطأ المهيكلة إلى دلوين: أخطاء الحقول وأخطاء على مستوى النموذج. ثم حدّث حالة الواجهة دون تغيير روابط النص.
struct ServerValidation: Decodable {
var fieldErrors: [String: String]
var formError: String?
}
// Map keys like "email" or "password" to your local field IDs.
ما يشعر عادةً بأنه محلي:
- ضع رسائل الحقل مضمّنة تحت الحقل، مستخدمًا صياغة الخادم عندما تكون واضحة.
- حرك التركيز إلى أول حقل فيه خطأ فقط بعد الإرسال، لا أثناء الكتابة.
- إذا أرجع الخادم عدة مشاكل، أظهر أول رسالة لكل حقل للحفاظ على قابلية القراءة.
- إذا كان لديك تفاصيل للحقل، لا ترجع إلى "حدث خطأ" كافتراضية.
مثال: المستخدم يرسل نموذج التسجيل، والخادم يعيد "البريد مستخدم بالفعل." احتفظ بالبريد الذي كتبه، أظهر الرسالة تحت حقل البريد، وضع التركيز على ذلك الحقل. إذا كان الخادم معطلاً، أظهر رسالة إعادة محاولة واحدة واترك كل الحقول كما هي.
كيفية عرض رسائل الخادم في المكان الصحيح
تشعر رسائل الخادم "بلا عدل" عندما تظهر في شريط عشوائي. ضع كل رسالة أقرب ما يكون للحقل الذي سبّبها. استخدم رسالة عامة فقط عندما لا تستطيع ربطها بحقل واحد حقًا.
ابدأ بترجمة حمولة خطأ الخادم إلى معرفات الحقول في SwiftUI. قد يرجع الخادم مفاتيح مثل email، password، أو profile.phone، بينما تستخدم واجهتك enum مثل Field.email وField.password. قم بالمطابقة مرة واحدة بعد الاستجابة، حتى يبقى باقي العرض متسقًا.
طريقة مرنة لنمذجة هذا هي الاحتفاظ بـ serverFieldErrors: [Field: [String]] وserverFormErrors: [String]. خزّن مصفوفات حتى لو عادةً ما تعرض رسالة واحدة. عندما تعرض خطأً مضمّنًا، اختر الرسالة الأكثر فائدة أولًا. على سبيل المثال، "البريد مستخدم بالفعل" أكثر فائدة من "بريد غير صالح" إذا ظهرت كلتاهما.
الأخطاء المتعددة لكل حقل شائعة، لكن عرضها كلها مزعج. في معظم الأحيان، أظهر الرسالة الأولى فقط مضمّنة واحتفظ بالباقي لعرض تفصيلي إن احتجت.
للأخطاء التي لا ترتبط بحقل (جلسة منتهية، حدوت وتيرة، "حاول لاحقًا"), ضعها قرب زر الإرسال حتى يراها المستخدم عند اتخاذه الإجراء. وتأكد أيضًا من مسح الأخطاء القديمة عند النجاح حتى لا تبدو الواجهة "عالقة".
أخيرًا، امسح أخطاء الخادم عندما يغير المستخدم الحقل ذي الصلة. عمليًا، يجب أن يزيل onChange لحقول مثل email serverFieldErrors[.email] حتى تعكس الواجهة فورًا "حسنًا، أنت تصلحه."
إمكانية الوصول والنبرة: خيارات صغيرة تشعر بأنها محلية
التحقق الجيد ليس فقط عن المنطق. إنه أيضًا عن كيف تُقرأ الرسالة، وكيف تُسمع، وكيف تتصرف مع Dynamic Type وVoiceOver واللغات المختلفة.
اجعل الأخطاء سهلة القراءة (وليست باللون فقط)
افترض أن النص قد يكبر. استخدم أنماط متوافقة مع Dynamic Type (مثل .font(.footnote) أو .font(.caption) دون أحجام ثابتة)، ودع تسميات الأخطاء تلتف. حافظ على تباعد ثابت حتى لا يقفز التخطيط كثيرًا عند ظهور خطأ.
لا تعتمد على اللون الأحمر فقط. أضف أيقونة واضحة، بادئة "خطأ:"، أو كلاهما. هذا يساعد الأشخاص ضعيفي الرؤية اللونية ويجعل المسح أسرع.
مجموعة من الفحوص السريعة عادةً ما تتماشى مع ذلك:
- استخدم نمط نص قابل للقراءة ويتوسع مع Dynamic Type.
- اترك الرسائل تلتف وتجنب القطع.
- أضف أيقونة أو بادئة مثل "خطأ:" بالإضافة إلى اللون.
- حافظ على تباين عالٍ في الوضعين الفاتح والداكن.
اجعل VoiceOver يقرأ الشيء الصحيح
عندما يكون الحقل غير صالح، يجب أن يقرأ VoiceOver التسمية والقيمة الحالية والخطأ معًا. إذا كانت رسالة الخطأ نصًا منفصلاً تحت الحقل، قد يتم تجاهلها أو قراءتها خارج السياق.
نمطان يساعدان:
- اجمع الحقل وخطأه في عنصر وصول واحد، حتى يُعلن الخطأ عند تركيز المستخدم على الحقل.
- اضبط تلميح الوصول أو القيمة لتشمل رسالة الخطأ (مثلاً: "كلمة المرور، مطلوب، يجب أن تكون 8 أحرف على الأقل").
النبرة مهمة أيضًا. اكتب رسائل واضحة وسهلة الترجمة. تجنّب العامية أو النكات أو العبارات الغامضة مثل "آسف". فضّل الإرشاد المحدد مثل "البريد مفقود" أو "يجب أن تتضمن كلمة المرور رقمًا".
مثال: نموذج تسجيل مع قواعد محلية وخادم
تخيل نموذج تسجيل له ثلاث حقول: البريد، كلمة المرور، وتأكيد كلمة المرور. الهدف هو نموذج يبقى هادئًا أثناء كتابة المستخدم، ثم يصبح مفيدًا عندما يحاول المتابعة.
ترتيب التركيز (ما يفعله Return)
مع SwiftUI FocusState، يجب أن يشعر كل ضغط Return كخطوة طبيعية.
- Return على البريد: نقل التركيز إلى كلمة المرور.
- Return على كلمة المرور: نقل التركيز إلى تأكيد كلمة المرور.
- Return على تأكيد كلمة المرور: إخفاء لوحة المفاتيح ومحاولة الإرسال.
- إذا فشل الإرسال: ضع التركيز على أول حقل يحتاج انتباهًا.
تلك الخطوة الأخيرة مهمة. إذا كان البريد غير صالح، يعود التركيز إلى البريد، وليس فقط إلى رسالة حمراء في مكان آخر.
متى تظهر الأخطاء
قاعدة بسيطة تحافظ على هدوء الواجهة: أظهر الرسائل بعد أن يكون الحقل ملموسًا (غادره المستخدم) أو بعد محاولة الإرسال.
- البريد: أظهر "أدخل بريدًا صالحًا" بعد مغادرة الحقل أو عند الإرسال.
- كلمة المرور: أظهر قواعدها (مثل الطول الأدنى) بعد المغادرة أو عند الإرسال.
- تأكيد كلمة المرور: أظهر "كلمتا المرور غير متطابقتين" بعد المغادرة أو عند الإرسال.
الآن جانب الخادم. افترض أن المستخدم أرسل والرابط البرمجي يعيد شيئًا مثل:
{
"errors": {
"email": "That email is already in use.",
"password": "Password is too weak. Try 10+ characters."
}
}
ما يراه المستخدم: يظهر رسالة الخادم مباشرة تحت البريد، وتظهر رسالة الشدة تحت كلمة المرور. يبقى تأكيد كلمة المرور هادئًا ما لم يفشل محليًا.
ما يفعلونه بعد ذلك: يتركز التركيز على البريد (أول خطأ في الخادم). يغيرون البريد، يضغطون Return للانتقال إلى كلمة المرور، يعدلون كلمة المرور، ثم يرسلون مرة أخرى. لأن الرسائل مضمّنة والتركير يتحرك بنية، يشعر النموذج بالتعاون بدلًا من التوبيخ.
الأخطاء الشائعة التي تجعل التحقق يبدو "غير-iOS"
يمكن أن يكون النموذج صحيحًا تقنيًا ومع ذلك يبدو خاطئًا. معظم مشاكل التحقق غير-iOS تتعلق بالتوقيت: متى تظهر رسالة الخطأ، متى يتحرك التركيز، وكيف تتفاعل مع الخادم.
خطأ شائع هو التحدث مبكرًا. إذا عرضت خطأً على أول ضغطة، يشعر الناس بالتوبيخ أثناء الكتابة. الانتظار حتى يصبح الحقل ملموسًا (تركه، أو محاولة الإرسال) عادةً ما يحل ذلك.
الاستجابات غير المتزامنة من الخادم قد تكسر التدفق أيضًا. إذا عاد طلب الاشتراك فجأة وبدأت تقفز بالتركيز إلى حقل آخر، سيبدو ذلك عشوائيًا. حافظ على التركيز حيث كان المستخدم آخر مرة، وحركه فقط عندما ينقر هو أو عندما تتعامل مع محاولة الإرسال.
فخ آخر هو مسح كل شيء عند كل تعديل. مسح كل الأخطاء عند أي تغيير يمكن أن يخفي المشكلة الحقيقية، خاصة مع رسائل الخادم. امسح فقط خطأ الحقل الجاري تحريره، واحتفظ بالباقي حتى تُصلح فعلاً.
تجنّب أزرار الإرسال التي تفشل بصمت. تعطيل الإرسال إلى الأبد دون شرح ما يجب إصلاحه يجبر المستخدمين على التخمين. إذا عطّلته، اقترن بتلميحات محددة، أو اسمح بالإرسال ثم دلهم على المشكلة الأولى.
الطلبات البطيئة والنقرات المزدوجة سهلة أن تُهمل. إذا لم تُظهر تقدمًا وتمنع الإرسال المزدوج، سيضغط المستخدم مرتين، يحصل على ردين، وينتهي بأخطاء مربكة.
إليك قائمة تحقق سريعة:
- أخرِج الأخطاء بعد الضباب أو الإرسال، ليس الحرف الأول.
- لا تحرك التركيز بعد استجابة الخادم ما لم يطلب المستخدم ذلك.
- امسح الأخطاء لكل حقل على حدة، وليس كل شيء دفعة واحدة.
- فسّر لماذا تم حظر الإرسال (أو اسمح بالإرسال مع إرشاد).
- أظهر التحميل وتجاهل النقرات الإضافية أثناء الانتظار.
مثال: إذا قال الخادم "البريد مستخدم بالفعل" (ربما من خلفية بنيتها في AppMaster)، احتفظ بالرسالة تحت البريد، اترك كلمة المرور كما هي، ودع المستخدم يحرر البريد دون إعادة تشغيل النموذج بالكامل.
قائمة تحقق سريعة وخطوات مقبلة
تجربة تحقق تبدو محلية تعتمد في الغالب على التوقيت وضبط النفس. يمكنك وضع قواعد صارمة وجعل الشاشة تشعر هادئة في نفس الوقت.
قبل النشر، تحقق مما يلي:
- تحقّق في الوقت المناسب. لا تُظهر الأخطاء على أول ضغطة ما لم تكن مفيدة بوضوح.
- حرك التركيز بهدف. عند الإرسال، انتقل إلى أول حقل غير صالح واجعل ما هو خطأ واضحًا.
- اجعل الصياغة قصيرة ومحددة. قل ما الذي يجب فعله بعد ذلك، لا ما فعله المستخدم "بالخطأ".
- احترم التحميل والمحاولات. عطّل زر الإرسال أثناء الإرسال، واحتفظ بالقيم المكتوبة إذا فشل الطلب.
- تعامل مع أخطاء الخادم كملاحظات حقل عندما يكون ذلك ممكنًا. طابق رموز الخادم لحقل، واستخدم رسالة علوية فقط للقضايا العامة.
ثم جرّبه كشخص حقيقي. امسك هاتفًا صغيرًا بيد واحدة وحاول إكمال النموذج بإبهامك. بعد ذلك، شغّل VoiceOver وتأكد من أن ترتيب التركيز وإعلانات الأخطاء وتسميات الأزرار ما زالت منطقية.
للغرض التصحيحي والدعم، يساعد تسجيل رموز تحقق الخادم (وليس الرسائل الخام) إلى جانب اسم الشاشة والحقل. عندما يقول المستخدم "لا يمكنني التسجيل"، يمكنك بسرعة معرفة ما إذا كان السبب email_taken أو weak_password أو انقضاء مهلة الشبكة.
للحفاظ على هذا الاتساق عبر التطبيق، قم بتوحيد نموذج الحقل (value، touched، local error، server error)، موضع الخطأ، وقواعد التركيز. إذا أردت بناء نماذج iOS محلية أسرع دون كتابة كل شاشة يدويًا، AppMaster (appmaster.io) يمكنه توليد تطبيقات SwiftUI إلى جانب خدمات خلفية، مما يسهل مزامنة قواعد التحقق بين العميل والخادم.


