Connect with us

Статьи

Что такое Realm

Realm предлагает современный подход к работе с локальными данными, минимизируя сложности ORM и SQL, что позволяет разработчикам сосредоточиться на бизнес-логике.

Опубликовано

/

     
     

Realm — это открытая кроссплатфорновая объектно-ориентированная база данных, разработанная специально для мобильных приложений. Она отличается от традиционных ORM (Object-Relational Mapping) тем, что работает напрямую с объектами, а не с SQL-таблицами, что делает её невероятно быстрой, эффективной и более удобной для разработчиков.

Realm позиционируется как современная замена SQLite и Core Data для iOS и Android, предлагая простой API, высочайшую производительность и современные функции, такие как синхронизация данных в реальном времени.

Кто стоит за Realm?

Изначально Realm разрабатывался одноимённым стартапом, но в 2018 году компания Realm была приобретена MongoDB.

Сегодня Realm является ключевой частью экосистемы MongoDB и часто упоминается как MongoDB Realm (или MongoDB Mobile/Atlas Device Sync). Это означает, что разработка и поддержка базы данных ведётся одним из крупнейших игроков на рынке NoSQL баз данных, а её интеграция с облачными сервисами MongoDB Atlas обеспечивает мощную и масштабируемую платформу для сквозной работы с данными.

Ключевые особенности Realm

1. Скорость и производительность: Zero-Copy Design

Realm — один из самых быстрых движков баз данных, доступных для мобильных устройств.

Прямая работа с объектами (Zero-Copy): Realm не копирует данные из базы в отдельные программные объекты. Вместо этого он отображает (maps) данные прямо в память, предоставляя прямой доступ к ним. Это устраняет накладные расходы на копирование и преобразование SQL-строк в объекты, что кардинально увеличивает скорость чтения и записи.

Ленивая загрузка: Объекты Realm загружаются «лениво» (по требованию), что минимизирует использование оперативной памяти.

2. Простота использования и объектная модель

Вместо написания SQL-запросов, вы работаете с обычными нативными объектами вашего языка программирования (Swift, Kotlin, Java, C#, JavaScript и т.д.).

Запросы: Запросы выполняются как простые вызовы методов или с использованием предикатов, что интуитивно понятно и снижает вероятность ошибок.

3. Реактивность и синхронизация в реальном времени (Atlas Device Sync)

Реактивность: Когда вы запрашиваете данные из Realm, вы получаете «живые» объекты. Любое изменение этих объектов в базе данных немедленно отражается в вашем коде, и Realm автоматически уведомляет ваш UI об этих изменениях. Это идеально подходит для создания реактивных пользовательских интерфейсов.

Синхронизация: Atlas Device Sync (преемник Realm Sync) позволяет легко синхронизировать локальные данные Realm между мобильными устройствами и облачной базой данных MongoDB Atlas в реальном времени, автоматически обрабатывая конфликты и обеспечивая доступность данных, даже когда устройство находится в офлайне.

Конечно! Вот пример работы с Realm на Swift для разработчиков iOS, демонстрирующий основные операции: определение модели, запись, чтение и выполнение запросов.

Пример работы с Realm на Swift (iOS)

Предположим, мы разрабатываем приложение для учета задач.

1. Установка Realm (с помощью Swift Package Manager)

Обычно это делается через Swift Package Manager (SPM), CocoaPods или Carthage.

2. Определение модели данных

В Realm, модель данных — это обычный класс, который наследуется от Object. Каждое свойство, которое вы хотите хранить, должно быть помечено @Persisted.

import RealmSwift

// Определяем модель "Задача"
final class Task: Object {
    // Первичный ключ (для уникальной идентификации и быстрого поиска)
    @Persisted(primaryKey: true) var _id: ObjectId
    
    // Свойства задачи
    @Persisted var name: String = ""
    @Persisted var isComplete: Bool = false
    @Persisted var createdAt: Date = Date()
    
    // Связь: Ссылка на родительский список задач (опционально)
    @Persisted var list: TaskList?
}

// Определяем модель "Список задач"
final class TaskList: Object {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var name: String = ""
    
    // Связь: Список задач, связанных с этим списком (обратная связь)
    // Results<T> - это живая коллекция, которая всегда актуальна
    @Persisted var tasks = RealmSwift.List<Task>()
}

3. Основные операции с Realm

3.1. Инициализация и получение экземпляра

Realm — это синглтон, который легко инициализируется:

// 1. Получаем экземпляр Realm (по умолчанию)
let realm = try! Realm()

3.2. Создание и запись

Все операции записи и удаления должны выполняться внутри транзакции realm.write.

func createAndSaveTasks() {
    let groceryList = TaskList()
    groceryList.name = "Продукты"

    let milkTask = Task(value: ["name": "Купить молоко", "isComplete": false])
    let breadTask = Task(value: ["name": "Хлеб", "isComplete": false])

    // Устанавливаем связь
    groceryList.tasks.append(milkTask)
    groceryList.tasks.append(breadTask)
    
    // Всегда используйте блок write для изменения базы данных
    try! realm.write {
        // Добавляем обе модели. Realm автоматически сохранит связанные объекты.
        realm.add(groceryList)
        
        print("✅ Список '\(groceryList.name)' и 2 задачи сохранены.")
    }
}

3.3. Чтение и запросы

Чтение в Realm происходит мгновенно, и вы получаете «живую» коллекцию (Results<T>), которая автоматически обновляется при изменении данных.

func readTasks() {
    // 1. Получаем все списки задач
    let allLists = realm.objects(TaskList.self)
    
    print("\n📦 Всего списков задач: \(allLists.count)")
    
    // 2. Выполняем запрос с фильтрацией (аналогично SQL WHERE)
    // Находим все задачи, которые еще не выполнены
    let incompleteTasks = realm.objects(Task.self).where {
        $0.isComplete == false
    }.sorted(byKeyPath: "createdAt", ascending: true)

    print("📝 Невыполненные задачи (по имени):")
    for task in incompleteTasks {
        print("- \(task.name) (Создана: \(task.createdAt))")
    }

    // 3. Доступ к связанным данным
    if let firstList = allLists.first {
        print("\n📎 Задачи в списке '\(firstList.name)':")
        for task in firstList.tasks {
            print("-- \(task.name)")
        }
    }
}

3.4. Обновление

Обновление, как и запись, должно происходить внутри транзакции realm.write.

func updateTaskStatus() {
    // Находим задачу "Хлеб"
    if let breadTask = realm.objects(Task.self).filter("name == 'Хлеб'").first {
        
        try! realm.write {
            // Просто изменяем свойство живого объекта
            breadTask.isComplete = true
            print("\n✔️ Задача '\(breadTask.name)' обновлена как выполненная.")
        }
    }
}

3.5. Удаление

Удаление также требует блока realm.write.

func deleteTask() {
    // Получаем все выполненные задачи
    let completedTasks = realm.objects(Task.self).filter("isComplete == true")
    
    // Если есть выполненные задачи, удаляем их
    if completedTasks.count > 0 {
        try! realm.write {
            // Удаляем коллекцию объектов
            realm.delete(completedTasks)
            print("\n🗑️ Все выполненные задачи удалены.")
        }
    }
}

4. Реактивность: Уведомления об изменениях

Одно из главных преимуществ Realm — возможность подписки на изменения коллекций в реальном времени, что идеально для обновления UITableView или UICollectionView.

// Свойство для хранения токена подписки, чтобы избежать утечек памяти
var notificationToken: NotificationToken?

func observeTasks() {
    let tasks = realm.objects(Task.self).sorted(byKeyPath: "createdAt")
    
    // Подписываемся на изменения в коллекции
    notificationToken = tasks.observe { (changes: RealmCollectionChange) in
        switch changes {
        case .initial:
            // Данные загружены впервые (первый запуск)
            print("\n🔔 Начальная загрузка данных.")
            // Обновляем UI/Table View
            
        case .update(_, let deletions, let insertions, let modifications):
            // Данные изменились
            print("🔔 Данные Realm обновлены:")
            print("   Удалено: \(deletions.count) элементов")
            print("   Вставлено: \(insertions.count) элементов")
            print("   Изменено: \(modifications.count) элементов")
            
            // Используйте эти индексы для обновления вашего UITableView/UICollectionView
            
        case .error(let error):
            // Произошла ошибка
            fatalError("\(error)")
        }
    }
    // Внимание: Не забудьте отменить подписку, когда объект (например, ViewController) будет удален.
    // notificationToken?.invalidate()
}

Этот пример демонстрирует, как легко и интуитивно можно работать с базой данных Realm, используя нативный синтаксис Swift, без необходимости писать сложный SQL.

Сравнение Realm с конкурентами

Характеристика Realm (MongoDB Realm) SQLite (+ Room/FMDB) Core Data (iOS/macOS)
Базовая технология Собственный нативный объектный движок (NoSQL-подобный) Реляционная база данных (SQL) Фреймворк для управления графом объектов
Парадигма работы Объектно-ориентированная (Zero-Copy) Реляционная (Таблицы и строки) Объектно-ориентированная (ORM-подобная)
Кроссплатформенность Полная (iOS, Android, React Native, Flutter, Xamarin) Нативный движок, но требует разных ORM/обёрток Только Apple (iOS, macOS, watchOS)
Скорость Максимальная (за счет Zero-Copy), быстрая работа с большими объемами данных Зависит от ORM, обычно медленнее Realm из-за накладных расходов на преобразование Быстрее чистого SQLite, но медленнее Realm
API Простой, нативный, нет SQL Требует SQL (или использования ORM, такого как Room) Сложнее, требует больше шаблонного кода
Реактивность (Уведомления) Встроена, «живые» объекты и коллекции Требует ручной реализации (или использования LiveData/Flow в Room) Требует ручной подписки на уведомления контекста
Синхронизация Встроена (Atlas Device Sync), готовое решение для офлайна/облака Требует написания собственной сложной логики синхронизации Требует написания собственной сложной логики синхронизации

Когда Realm — лучший выбор?

  1. Приоритет производительности: Если ваше приложение интенсивно работает с данными (частые чтения/записи, большие объемы) и вам нужна максимальная скорость.
  2. Реактивный интерфейс: Если вы используете архитектуру, где UI должен мгновенно реагировать на любые изменения в базе данных (чаты, финансовые трекеры, панели мониторинга).
  3. Кроссплатформенность: Если вы разрабатываете одно приложение сразу для iOS и Android и хотите использовать единый код для работы с данными.
  4. Требуется синхронизация: Если вашему приложению необходимо работать в офлайн-режиме, а затем бесшовно синхронизировать данные с бэкендом (MongoDB Atlas) без написания сложного серверного кода.

Realm предлагает современный подход к работе с локальными данными, минимизируя сложности ORM и SQL, что позволяет разработчикам сосредоточиться на бизнес-логике.

Если вы нашли опечатку - выделите ее и нажмите Ctrl + Enter! Для связи с нами вы можете использовать info@apptractor.ru.
Telegram

Популярное

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: