ترحيل قواعد البيانات في Swift (iOS/macOS)
غالبًا ما يتطلب تطوير التطبيقات لنظامي iOS وmacOS العمل مع قواعد البيانات المحلية. مع تطور التطبيق، يتغير هيكل البيانات حتمًا: تتم إضافة حقول جديدة، أو تغيير الأنواع، أو حذف الكيانات القديمة. بدون آلية ترحيل صحيحة، يمكن أن تؤدي هذه التغييرات إلى فقدان بيانات المستخدم أو تعطل التطبيق. في هذه المقالة، سنستعرض الأدوات والطرق الرئيسية لتنفيذ ترحيل قواعد البيانات في Swift، بالإضافة إلى تقديم أمثلة عملية للحلول الشائعة.
لماذا الترحيل مهم؟
يضمن ترحيل قواعد البيانات:
- الحفاظ على البيانات — لا يتم فقدان سجلات المستخدم عند تحديث المخطط.
- التوافق العكسي — يستمر التطبيق في العمل مع الإصدارات القديمة من البيانات.
- مرونة التطوير — إمكانية تغيير نموذج البيانات بشكل تكراري دون تدخل يدوي.
الأدوات الرئيسية للترحيل في Swift
1. Core Data + NSPersistentContainer
يوفر إطار العمل المدمج من Apple ترحيلًا تلقائيًا وخفيفًا. للتغييرات المعقدة، يتم استخدام إصدار يدوي للنموذج.
// إعداد الحاوية مع دعم الترحيلlet container = NSPersistentContainer(name: "MyAppModel")container.persistentStoreDescriptions.first?.shouldMigrateStoreAutomatically = truecontainer.persistentStoreDescriptions.first?.shouldInferMappingModelAutomatically = true
container.loadPersistentStores { description, error in if let error = error { fatalError("Failed to load store: \\(error)") }}للترحيل اليدوي، يتم إنشاء إصدارات النموذج (.xcdatamodeld) و NSMappingModel:
let sourceModel = NSManagedObjectModel(contentsOf: sourceURL)!let destinationModel = NSManagedObjectModel(contentsOf: destinationURL)!let mappingModel = NSMappingModel(from: [sourceModel, destinationModel], forSourceModel: sourceModel, destinationModel: destinationModel)
let manager = NSMigrationManager(sourceModel: sourceModel, destinationModel: destinationModel)try? manager.migrateStore(from: sourceURL, sourceType: NSSQLiteStoreType, options: nil, with: mappingModel, toDestinationURL: destinationURL, destinationType: NSSQLiteStoreType, destinationOptions: nil)2. GRDB.swift — مشغل SQLite حديث
يقدم GRDB.swift آلية ترحيل مرنة تعتمد على تسجيل الخطوات. يتم تنفيذ الترحيلات بشكل تسلسلي وذري.
import GRDB
var migrator = DatabaseMigrator()
// تسجيل الترحيل الأولmigrator.registerMigration("v1_create_users") { db in try db.create(table: "users") { t in t.autoIncrementedPrimaryKey("id") t.column("name", .text).notNull() t.column("email", .text).unique() }}
// تسجيل الترحيل الثاني (إضافة حقل)migrator.registerMigration("v2_add_age") { db in try db.alter(table: "users") { t in t.add(column: "age", .integer).defaults(to: 0) }}
// تطبيق الترحيلات عند بدء التطبيقlet dbQueue = try DatabaseQueue(path: "/path/to/database.sqlite")try migrator.migrate(dbQueue)مزايا GRDB.swift: استعلامات مصنفة، دعم المعاملات، إلغاء الترحيل بسهولة.
3. Realm Swift (حاليًا Atlas Device SDK)
يعالج Realm معظم الترحيلات تلقائيًا، ولكن للتغييرات المعقدة، يلزم تحديث صريح للمخطط.
import RealmSwift
let config = Realm.Configuration( schemaVersion: 2, migrationBlock: { migration, oldSchemaVersion in if oldSchemaVersion < 1 { migration.enumerateObjects(ofType: "User") { oldObject, newObject in newObject?["fullName"] = "\\(oldObject!["firstName"] ?? "") \\(oldObject!["lastName"] ?? "")" }