iOS / Swift / التزامن وحدود البيانات / الدرس 11
التخزين ذو الإصدار وسياقات SwiftData
ميّز التسلسل والتغييرات المتتبعة في الذاكرة والحفظ والمزامنة المعتمدة.
في هذه الصفحة
أهداف الدرس
- سمّ ضمان كل طبقة تخزين
- أضف إصدارا لغلاف مسودة قابل للنقل
- اربط حاوية النموذج المقصودة
سمّ ضمان كل طبقة تخزين
تختلف مراحل نص JSON وكائن نموذج معدل وحفظ محلي ناجح وأمر مؤكد من الخادم. ينتج التسلسل بايتات فقط ولا يضمن بقاءها بعد الإنهاء. تتبع SwiftData النماذج بحاوية وسياق، ويبقى للتطبيق اختيار التحقق وحدود الحفظ والترحيل والخصوصية والمزامنة. عامل المخزن القابل للإعادة خلاف المسودة المهمة. حدّد العمر والحساسية والإصدار والتعافي قبل واجهة التخزين، فآلية التفضيلات ليست تلقائيا مكانا للأسرار أو المعاملات.
أضف إصدارا لغلاف مسودة قابل للنقل
يفك المقتطف الأول مسودة ذات إصدار باستخدام Codable ثم يفحص رقم المخطط. يميز القارئ المحتوى غير المدعوم من المقبول بدلا من تفسير حقول متغيرة بافتراض قديم. ينبغي لترحيل مستقبلي حفظ المعنى والتحقق من ناتجه لا تغيير المفاتيح حتى ينجح الفك. العينة نص مصطنع فقط ولا يُفتح ملف أو قاعدة هنا. ولعمل مهم ينبغي للإصدار غير المدعوم مسار استرداد أو تصدير بدلا من حذف صامت خلف شاشة فارغة.
import Foundation
struct DraftEnvelope: Codable {
let schema: Int
let title: String
}
enum DraftFailure: Error { case unsupportedSchema }
func readDraft(_ bytes: Data) throws -> DraftEnvelope {
let value = try JSONDecoder().decode(DraftEnvelope.self, from: bytes)
guard value.schema == 1 else { throw DraftFailure.unsupportedSchema }
return value
}
let bytes = Data(#"{"schema":1,"title":"Maps"}"#.utf8)
// try readDraft(bytes).title -> "Maps"
Schema 1 accepts Maps; another schema throws unsupportedSchema.
يثبت فك البايتات المحلية قبول الصيغة فقط لا ديمومة الملف أو ترحيل قاعدة.
اربط حاوية النموذج المقصودة
تحتاج SwiftData إلى حاوية تعرف مخطط النماذج وإعداد التخزين. يأتي سياق بيئة SwiftUI من الحاوية المرتبطة؛ فلا تفترض أن نجاح البحث في البيئة يثبت المخزن الصحيح. يعلن المقتطف الثاني نموذجا صغيرا ويطلب حفظا صريحا في سياق مقدم على الممثل الرئيسي. يربط المستدعي الحاوية المطلوبة ويحقنها ويعالج الفشل. هذا مقتطف توضيحي لا ينشئ مخزنا حقيقيا أو يعدله. ولا يثبت الحفظ المحلي قبول نظام بعيد للبيانات.
import SwiftData
@Model final class SavedDraft {
var title: String
init(title: String) { self.title = title }
}
@MainActor
func insertDraft(title: String, context: ModelContext) throws {
let draft = SavedDraft(title: title)
context.insert(draft)
try context.save()
}
The supplied context tracks a new draft and attempts an explicit save.
يتطلب بيئة SwiftData متوافقة وحاوية تشمل SavedDraft. لم يُفتح مخزن أو يُحفظ أو يُستعلم أثناء التأليف.
احفظ اتساق أعمار السياق والنموذج
ينتمي النموذج الدائم إلى سياق مدار ولا ينبغي تمريره اعتباطيا بين حدود التزامن كقيمة Sendable عادية. استخدم معرّفات مستقرة أو لقطات ثابتة وحلها في نطاق الحفظ المستقبل بواجهات موثقة. يرتبط سياق البيئة الرئيسي بالممثل الرئيسي؛ ويحتاج الحفظ الخلفي إلى تصميم عزل مدعوم صريح. لا تصلح التشخيصات بتعليقات غير متحققة. وقد يؤثر rollback في تعديلات متعددة ضمن سياق مشترك، لذا قد تناسب مسودة مستقلة إلغاء النموذج أكثر من التراجع عن عمل غير مرتبط.
اختر سياسة الحفظ والفشل عن قصد
ليس الحفظ التلقائي بديلا لتحديد وقت قبول المنتج للتعديل. إذا احتاج الأمر تأكيدا فاستدع حد الحفظ المناسب وعالج خطأه قبل النجاح. قد يترك الفشل تغييرات متتبعة بالذاكرة تظهر في الواجهة؛ فميّزها من المحفوظ ووفّر إعادة أو تعافيا. يحتاج تطور المخطط إلى خطة ترحيل مراجعة وعينات سابقة مدعومة. لا تحذف المخزن افتراضيا لفشل الترحيل إذا حوى عمل المستخدم. شخّص هوية الحاوية والمخطط والإعداد أولا.
اختبر حدود الصيغة والحفظ مستقلة
تثبت عينات نقية فك الغلاف ومنطق الترحيل دون قاعدة حقيقية. ويمكن لحاوية SwiftData معزولة في الذاكرة ببيئة SDK مصرح بها اختبار التسجيل والإدراج والجلب ومعالجة الحفظ حيث يمكن ضبطها. لا تثبت ديمومة القرص أو التعافي بعد الإنهاء أو مزامنة السحابة. أبقها مهام تكامل مستقلة. لم تُنفذ عملية SwiftData للدورة. ولا يثبت فحص ملفات الدروس JSON سلوك حفظ Apple ولا تدّعي الدورة ذلك.
الأخطاء الشائعة وإصلاحها
يُعلن التعديل المرئي محفوظا دائما
- لماذا يحدث؟
- اختلط التغير المتتبع في الذاكرة بنجاح الحفظ.
- كيف تصلحه؟
- استخدم حد قبول صريحا وعالج فشل الحفظ.
- كيف تتجنب تكراره؟
- اختبر حالتي عدم الحفظ وفشله.
يُستعمل نموذج عبر سياق غير مرتبط
- لماذا يحدث؟
- عبرت ملكية الكائن نطاقات الحفظ أو الممثل.
- كيف تصلحه؟
- مرّر الهوية أو قيما ثابتة وحلها بالنطاق المطلوب.
- كيف تتجنب تكراره؟
- وثّق ملكية السياق مع واجهات المستودع.
يحذف تعافي الترحيل مسودات مهمة
- لماذا يحدث؟
- اختير حذف المخزن قبل التشخيص والتعافي.
- كيف تصلحه؟
- احفظ البيانات وافحص توافق المخطط والحاوية قبل تعاف مراجع.
- كيف تتجنب تكراره؟
- احفظ عينات الإصدارات السابقة ومسارات الاسترداد.
اختبر فهمك
1. هل يثبت نجاح تحويل Codable ذهابا وإيابا بقاء المسودة بعد إعادة البدء؟
اعرض الحل المشروح
لا. يثبت ترميز القيم وفكها بتلك الصيغة. تحتاج الديمومة واكتمال الكتابة وحماية الملفات والتعافي بعد البدء إلى دليل مستقل في بيئة الحفظ. سمّ كل نتيجة بحسب حدها.
2. لماذا قد يكون rollback لسياق مشترك أوسع من إلغاء نموذج؟
اعرض الحل المشروح
قد يحوي السياق تغييرات تدفقات أخرى. وقد يسقط التراجع تلك التعديلات مع النموذج الحالي. فضّل مسودة معزولة أو تصميم معاملة محدودا عمدا واختبر حفظ العمل غير المرتبط عند الإلغاء.
أهم ما تعلمته
- سمّ ضمان كل طبقة تخزين
- اختبر حدود الصيغة والحفظ مستقلة