iOS / Swift / التزامن وحدود البيانات / الدرس 9
Observation ونماذج الممثل الرئيسي
افصل تتبع التغير وسلطة التعديل وعزل الممثل وملكية الموارد في نموذج واجهة مشترك.
في هذه الصفحة
أهداف الدرس
- تتبع Observation القراءات لا كل شؤون التطبيق
- اجعل العزل صريحا
- امنح التحرير عبر سطح رابط مقصود
تتبع Observation القراءات لا كل شؤون التطبيق
تتيح Observation اعتماد عرض SwiftUI على الخصائص المراقبة التي يقرأها أثناء وصف body. في خط iOS 17 أو أحدث تضيف @Observable دعم التتبع إلى النموذج. ولا تختار تلقائيا مالكا واحدا أو تفوّض التعديلات أو ترتب كل التدفقات غير المتزامنة أو تحفظها. تبقى هذه قرارات تصميم. ركّز النموذج على المعلومات والأوامر اللازمة للواجهة ودع المستودع يملك سياسة البيانات. ووثّق عمر النموذج المشترك بين شاشتين بدلا من إنشائه مستقلا في كل منهما وتباعد النسخ.
اجعل العزل صريحا
يضع المقتطف الأول @MainActor و@Observable على نموذج الواجهة. يحدد الأول عزل خصائصه المتغيرة، ويتيح الثاني تتبع الاعتماديات. يعالجان مشكلتين مختلفتين. تشتق visibleLabels من labels وquery فتتجنب مصفوفة مرشحة ثانية متغيرة مستقلة. يناسب الاشتقاق المباشر هذه البيانات الصغيرة. وإذا كلف الترشيح فقِس قبل التخزين وأدرج كل الاعتماديات في الإبطال. ولا تضف unchecked Sendable لجعل النموذج قابلا للتعديل بحرية من مهام متزامنة اعتباطية.
import Foundation
import Observation
@MainActor @Observable
final class LabelModel {
var query = ""
private(set) var labels = ["Maps", "Rivers"]
var visibleLabels: [String] {
labels.filter { query.isEmpty || $0.localizedCaseInsensitiveContains(query) }
}
func replaceLabels(_ next: [String]) { labels = next }
}
An empty query exposes both labels; query Maps exposes Maps.
توفر Foundation مقارنة النص المحلية. ويبقى تتبع التغير وعزل الممثل تعليقين مستقلين.
امنح التحرير عبر سطح رابط مقصود
يستقبل المقتطف الثاني النموذج المشترك ويستخدم @Bindable لإنشاء رابط بالاستعلام القابل للتحرير. ينبغي للأب حفظ النموذج تحت نطاق ملكية مستقر مقصود. يبدد تمرير نموذج جديد كل عرض مصدر الحقيقة المشترك. يقرأ العرض visibleLabels فيثبت الاعتماديات عبر الحساب. يناسب الرابط مسودة البحث القابلة للعكس؛ ويبقى الحفظ المميز أمرا يتحقق من مدخلاته. ضيّق سطح التعديل كي لا تعيّن الواجهة علم انتظار دون بدء العملية المقابلة.
import SwiftUI
@MainActor
struct LabelScreen: View {
@Bindable var model: LabelModel
var body: some View {
VStack {
TextField("Filter labels", text: $model.query)
ForEach(model.visibleLabels, id: \.self) { label in Text(label) }
}
}
}
Editing the filter changes the derived visible labels under the shared model.
التسميتان المصطنعتان فريدتان وثابتتان. تستعمل صفوف المجال العامة معرّفات سجلات مستقرة بدلا من عناوين متغيرة.
لا تخلط عزل الممثل الرئيسي بذرية التدفق
يمكن لدالة الممثل الرئيسي التعليق عند await والسماح لفعل آخر بتغيير النموذج قبل المتابعة. لذلك قد يكتمل تحميلان بترتيب مخالف دون سباق بيانات. أضف سياسة أوامر وفحوص حداثة حين تهم هوية المدخل أو الجلسة. ولا تثبت إشعارات المراقبة قبول الحفظ لدى خدمة معتمدة. انشر حالات تحميل ونجاح وفشل متسقة بحسب العقد. واحفظ النتيجة السابقة أثناء التحديث إذا قصد ذلك، لا تمحها كأثر لإنشاء المهمة.
امتلك الاشتراكات والمهام مستقلة عن البيانات المراقبة
ليست الخاصية المتتبعة سياسة تنظيف. إذا بدأ النموذج تدفقا أو اشتراك إشعارات أو Task محفوظة فحدّد متى تتوقف وهل يعيش النموذج بعد آخر عرض. لا ينبغي لنموذج نطاق عرض وآخر نطاق حساب اتباع قاعدة إنهاء واحدة لمجرد مراقبتهما. أبعد قدرات التقديم العابرة عن بنية البيانات؛ فلا تحفظ إجراءات بيئة SwiftUI داخل المستودعات. أعد نتيجة تطبيق ودع مالك الواجهة الحالي يختار تقديمها.
تحقّق من النموذج والعرض باستقلال
اختبر أوامر النموذج تحت العزل المعلن باعتماديات مصطنعة وأكّد الحالة المقبولة. ثم افحص أن العرض يقرأ الخصائص اللازمة ويعكسها. يثبت اختبار النموذج الترشيح لا جودة تسمية الحقل أو حفظ التركيز. أضف حالة مالك مشترك يراقبه عرضان وحالة تصفير ملكية مقصودة. واذكر نمط Swift وSDK للفحوص المنفذة. هنا لم يُختبر توسيع ماكرو Observation أو المترجم أو المحاكي أو الجهاز.
الأخطاء الشائعة وإصلاحها
يُعدّل نموذج مراقب عبر حدود العزل
- لماذا يحدث؟
- اعتُبر تتبع التغير حماية تزامن.
- كيف تصلحه؟
- أعلن عزل الممثل واعبره بالوصول غير المتزامن المدعوم.
- كيف تتجنب تكراره؟
- راجع تشخيص التزامن قبل إسكاته.
تعرض شاشتان نسختين مستقلتين دون قصد
- لماذا يحدث؟
- تنشئ كل شاشة نموذجا بدلا من استقبال المالك المشترك.
- كيف تصلحه؟
- أنشئ النموذج في النطاق المشترك المقصود واحقنه.
- كيف تتجنب تكراره؟
- اختبر تغيرات عرضين بكائن محفوظ واحد.
تتباعد البيانات المرشحة عن الاستعلام
- لماذا يحدث؟
- لم تُحدّث مصفوفة مرشحة زائدة باتساق.
- كيف تصلحه؟
- اشتقها أو مركز إبطال المخزن لدى النموذج.
- كيف تتجنب تكراره؟
- اختبر تغير الاستعلام واستبدال مصدر بالطول نفسه.
اختبر فهمك
1. هل تتضمن @Observable معنى @MainActor؟
اعرض الحل المشروح
لا. تتبع Observation الوصول والتغير، ويتحكم العزل في الوصول للحالة. علّق نموذج الواجهة صراحة بحسب افتراضات المشروع، ووثّق إعداد المترجم الذي يغير العزل الافتراضي أيضا.
2. لماذا يناسب الرابط query وقد لا يناسب حجزا مؤكدا؟
اعرض الحل المشروح
الاستعلام تفضيل محلي قابل للتحرير وتغييره العملية المقصودة. يحتاج الحجز إلى تحقق وتفويض وانتظار وتأكيد معتمد. أتحه بأمر ونتيجة بدلا من اعتبار كتابة خاصية اعتباطية نجاحا.
أهم ما تعلمته
- تتبع Observation القراءات لا كل شؤون التطبيق
- تحقّق من النموذج والعرض باستقلال