ORM для Swift (iOS/macOS): сравнение и примеры использования

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

ORM для Swift (iOS/macOS): сравнение и примеры

При разработке приложений под iOS и macOS работа с локальными данными — одна из ключевых задач. Object-Relational Mapping (ORM) позволяет разработчикам работать с базами данных, используя объектно-ориентированный подход, вместо написания сырых SQL-запросов. В этой статье мы рассмотрим четыре основных ORM-решения для Swift: Core Data, Realm, GRDB и SwiftData. Вы узнаете их сильные и слабые стороны, а также увидите примеры кода для каждой технологии.

1. Core Data

Core Data — это фреймворк от Apple, встроенный в iOS, macOS, tvOS и watchOS. Он не является чистой ORM (скорее, persistence framework), но выполняет все функции ORM: управление объектной моделью, сохранение, откат изменений и связывание с UI через NSFetchedResultsController.

Преимущества:

  • Глубокая интеграция с экосистемой Apple (iCloud, SwiftUI, Combine)
  • Встроенная поддержка версионирования и миграции данных
  • Мощные предикаты и сортировки

Недостатки:

  • Сложная настройка и много boilerplate-кода
  • Проблемы с многопоточностью (требуется строгий контекст)
  • Низкая производительность при больших объёмах данных

Пример использования:

import CoreData

// 1. Создаём модель (в Xcode Data Model Editor)
// 2. Инициализируем контейнер
let container = NSPersistentContainer(name: "MyModel")
container.loadPersistentStores { _, error in
    if let error = error { fatalError("Failed to load: \(error)") }
}

// 3. Сохранение объекта
let context = container.viewContext
let user = User(context: context)
user.name = "Иван"
user.age = 30
try? context.save()

// 4. Запрос
let request: NSFetchRequest<User> = User.fetchRequest()
request.predicate = NSPredicate(format: "age > %@", 18)
let adults = try? context.fetch(request)

2. Realm

Realm — это популярная сторонняя ORM, созданная для мобильных платформ. Она работает быстрее Core Data в большинстве сценариев и проще в использовании. Realm использует собственный движок хранения, а не SQLite.

Преимущества:

  • Высокая скорость чтения/записи
  • Простой API (без NSManagedObject)
  • Встроенная поддержка реактивных обновлений (через Realm Notifications)

Недостатки:

  • Закрытый код (не open-source в полном смысле)
  • Проблемы с миграцией при изменении модели
  • Ограниченная поддержка сложных запросов (JOIN, подзапросы)

Пример использования:

import RealmSwift

// 1. Определяем модель
class User: Object {
    @Persisted var name: String = ""
    @Persisted var age: Int = 0
}

// 2. Создаём и сохраняем
let realm = try! Realm()
let user = User()
user.name = "Мария"
user.age = 25
try! realm.write {
    realm.add(user)
}

// 3. Запрос
let adults = realm.objects(User.self).filter("age > 18")

3. GRDB

GRDB — это легковесная ORM для Swift, построенная поверх SQLite. Она даёт полный контроль над SQL-запросами, но при этом предоставляет удобный объектно-ориентированный интерфейс. GRDB особенно популярна среди разработчиков, которые хотят сочетать мощь SQL с удобством Swift.

Преимущества:

  • Полный доступ к SQL (можно писать сложные запросы)
  • Высокая производительность (близка к чистому SQLite)
  • Поддержка Swift Concurrency (async/await)

Недостатки:

  • Требует знания SQL
  • Меньше документации, чем у Core Data
  • Нет встроенной поддержки iCloud

Пример использования:

import GRDB

// 1. Определяем модель (Codable + FetchableRecord)
struct User: Codable, FetchableRecord, PersistableRecord {
    var id: Int64?
    var name: String
    var age: Int
}

// 2. Подключаемся к БД
let dbQueue = try DatabaseQueue(path: "/path/to/database.sqlite")

// 3. Сохранение
try dbQueue.write { db in
    let user = User(name: "Алексей", age: 28)
    try user.insert(db)
}

// 4. Запрос
let adults = try dbQueue.read { db in
    try User.filter(Column("age") > 18).fetchAll(db)
}

4

Рекомендаций