Миграции баз данных в Swift (iOS/macOS): обзор инструментов и примеры
Миграции баз данных — это процесс контролируемого изменения схемы данных (таблиц, индексов, связей) без потери уже существующей информации. В экосистеме Swift для платформ Apple (iOS, macOS, watchOS, tvOS) разработчики используют несколько подходов: от встроенного Core Data до сторонних библиотек, таких как GRDB.swift и Fluent. В этой статье мы разберём ключевые инструменты, их возможности и приведём практические примеры кода.
1. Core Data и миграции (лёгкие и ручные)
Core Data — стандартный фреймворк Apple для работы с объектной моделью. Миграции делятся на два типа:
- Лёгкая миграция (Lightweight Migration) — автоматическая, если изменения не затрагивают сложные преобразования (добавление атрибутов, удаление, переименование с mapping model).
- Ручная миграция (Manual Migration) — требуется, когда нужно изменить типы данных, объединить сущности или выполнить кастомные преобразования.
Пример настройки лёгкой миграции в Swift:
import CoreData
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "MyDataModel")
let description = container.persistentStoreDescriptions.first
description?.shouldMigrateStoreAutomatically = true
description?.shouldInferMappingModelAutomatically = true
container.loadPersistentStores { _, error in
if let error = error {
fatalError("Ошибка загрузки Core Data: \(error)")
}
}
return container
}()
2. GRDB.swift — современная SQLite-библиотека с миграциями
GRDB.swift — это мощная библиотека для работы с SQLite, которая предлагает встроенный механизм миграций. Она позволяет версионировать схему базы данных и выполнять изменения последовательно.
Установка через Swift Package Manager:
// Package.swift
dependencies: [
.package(url: "https://github.com/groue/GRDB.swift.git", from: "6.0.0")
]
Пример миграции с GRDB.swift:
import GRDB
var migrator = DatabaseMigrator()
// Миграция 1: создание таблицы
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()
}
}
// Миграция 2: добавление столбца
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)
3. Fluent (Vapor) — ORM для серверного Swift
Fluent — это ORM, входящая в состав фреймворка Vapor (серверный Swift для macOS). Миграции в Fluent описываются как классы, реализующие протокол Migration.
Пример миграции для Fluent 4:
import Fluent
struct CreateUser: Migration {
func prepare(on database: Database) -> EventLoopFuture<Void> {
database.schema("users")
.id()
.field("name", .string, .required)
.field("email", .string, .required).unique(on: "email")
.create()
}
func revert(on database: Database) -> EventLoopFuture<Void> {
database.schema("users").delete()
}
}
// Регистрация в configure.swift
app.migrations.add(CreateUser())
try app.autoMigrate().wait()
4. Сравнение инструментов
- Core Data — подходит для приложений Apple с привязкой к объектной модели. Миграции часто автоматические, но сложные сценарии требуют mapping model.
- GRDB.swift — идеален для проектов, где нужен прямой контроль над SQL. Поддерживает версионирование, откат и тестирование миграций.
- Fluent — выбор для серверных приложений на Vapor. Интегрирован с PostgreSQL, MySQL, SQLite. Миграции легко откатываются.
5. Рекомендации по выбору
Если вы разрабатываете классическое iOS/macOS приложение с Core Data — используйте лёгкие миграции. Для проектов с SQLite и требованиями к производительности (например, чаты, кэши) выбирайте GRDB.swift. Для серверной части на Swift (API, бэкенд) — Fluent.
Важно: Всегда тестируйте миграции на тестовой базе данных перед выпуском в продакшн. Используйте версионирование миграций