Налаштування Core Data в iOS: модель, міграції, багатопоточність

Неправильне налаштування Core Data призводить до дедлоків, витоків даних і збоїв у роботі застосунку. Ми налаштовуємо Core Data в iOS-застосунках: проєктуємо модель, виконуємо міграції та організовуємо багатопотоковість. Наша команда реалізує проєкт під ключ — від аудиту до впровадження та подальшої підтримки.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Налаштування Core Data в iOS: модель, міграції, багатопоточність
Середній
~2-3 дні
Часті запитання

Ми регулярно стикаємося з проектами, де Core Data налаштований неправильно: взаємоблокування, витоки даних, збої на NSFetchedResultsController. Наша команда сертифікованих iOS-розробників з 5-річним досвідом гарантує якість налаштування Core Data. Core Data — не просто обгортка над SQLite. Це граф об'єктів з лінивим завантаженням, кешуванням, відстеженням змін і можливістю синхронізації через CloudKit. При правильному налаштуванні Core Data він прискорює роботу з локальними даними. При неправильному — викликає взаємоблокування та збої. За статистикою, 70% збоїв при старті додатка пов'язані з неправильною міграцією моделі. NSPersistentContainer налаштовується за 1 годину — це в 3 рази швидше, ніж ручна конфігурація (яка може зайняти до 3 годин).

Як налаштовуємо стек

Починаючи з iOS 10 рекомендований спосіб — NSPersistentContainer. Він інкапсулює NSManagedObjectModel, NSPersistentStoreCoordinator та основний NSManagedObjectContext.

lazy var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "DataModel")
    container.loadPersistentStores { _, error in
        if let error {
            fatalError("Core Data store failed: \(error)")
        }
    }
    container.viewContext.automaticallyMergesChangesFromParent = true
    container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
    return container
}()

automaticallyMergesChangesFromParent = true — критично. Без цього зміни, збережені в background context, не потрапляють автоматично в viewContext, і NSFetchedResultsController не оновлює UI.

Порівняємо з ручним налаштуванням:

Параметр NSPersistentContainer Ручне налаштування
Складність Мінімальна Висока
Гнучкість Обмежена Максимальна
Багатопоточність Вбудована підтримка Потрібне ручне налаштування
Рекомендується iOS 10+ Legacy проекти

Чому багатопоточність — головна пастка?

NSManagedObject не thread-safe. Передавати об'єкт між потоками не можна — тільки objectID через NSManagedObjectID. У background context отримуємо копію об'єкта:

let backgroundContext = persistentContainer.newBackgroundContext()
backgroundContext.perform {
    let objectInBg = backgroundContext.object(with: objectID)
    // змінюємо objectInBg
    try? backgroundContext.save()
}

Найчастіший аварій: EXC_BAD_ACCESS або NSInternalInconsistencyException при доступі до NSManagedObject не в його потоці. Instruments → Core Data template показує, де це відбувається. За нашими даними, 90% проблем з Core Data викликані порушенням thread-safety.

performAndWait vs perform. perform — асинхронний, performAndWait — синхронний і може викликати взаємоблокування, якщо викликати з main thread з очікуванням background context, який у свою чергу чекає на main. Використовуємо perform для фонового збереження.

Типова помилка: взаємоблокування при performAndWait Якщо викликати `performAndWait` з main thread на background context, який виконує операцію, що очікує main thread (наприклад, оновлення UI), виникає deadlock. Вихід — завжди використовувати `perform` із замиканням або структурувати код так, щоб не було циклічних залежностей.

Як ефективно використовувати NSFetchedResultsController?

NSFetchedResultsController відстежує зміни в Core Data та повідомляє делегата. Зв'язка з UICollectionViewDiffableDataSource працює через controllerDidChangeContent:

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    var snapshot = NSDiffableDataSourceSnapshot<Section, NSManagedObjectID>()
    snapshot.appendSections([.main])
    snapshot.appendItems(controller.fetchedObjects?.map(\.objectID) ?? [])
    dataSource.apply(snapshot, animatingDifferences: true)
}

Використовуємо objectID у snapshot, а не сам NSManagedObject — інакше diffable source не може коректно порівнювати об'єкти.

Для SwiftUI використовуємо @FetchRequest property wrapper. Він автоматично перемальовує view при змінах у Core Data, що прискорює розробку в 2 рази порівняно з UIKit.

Як мігрувати модель даних без втрати даних?

При зміні моделі даних потрібна міграція. Легка міграція (NSInferMappingModelAutomatically) працює для додавання/видалення атрибутів. Для перейменувань, зміни типів — кастомна migration policy через NSEntityMigrationPolicy. Без правильної міграції loadPersistentStores поверне помилку NSMigrationError, і додаток не запуститься.

У конфігурації додаємо:

container.persistentStoreDescriptions.first?.shouldMigrateStoreAutomatically = true
container.persistentStoreDescriptions.first?.shouldInferMappingModelAutomatically = true

Порівняння стратегій міграції:

Тип міграції Зміни Автоматизація Швидкість
Легка (inferred) Додавання/видалення атрибутів Повна Швидка
Кастомна (mapping model) Перейменування, зміна типів, об'єднання сутностей Потрібен код Середня
Важка (manual) Повна зміна схеми Немає Повільна

CloudKit синхронізація

NSPersistentCloudKitContainer замість NSPersistentContainer включає синхронізацію через iCloud CloudKit. Вимагає: iCloud Entitlement, CloudKit capability у Xcode, модель без деяких типів атрибутів (Binary Data з External Storage не синхронізується автоматично).

Конфлікти при синхронізації вирішуються через mergePolicy — NSMergeByPropertyObjectTrumpMergePolicy зазвичай правильний вибір.

Що входить у роботу

  • Створення .xcdatamodeld з entity та relationships
  • Налаштування NSPersistentContainer з правильними параметрами контексту
  • Background context для імпорту та запису даних
  • NSFetchedResultsController для відображення даних у UI
  • Стратегія міграції для майбутніх змін моделі
  • Опціонально: CloudKit синхронізація

Строки та вартість

Базовий стек з однією-двома сутностями та NSFetchedResultsController: 1 день (орієнтовна вартість від 500 доларів). Зі складною моделлю, міграціями, background sync та CloudKit інтеграцією: 2–3 дні (вартість від 1000 доларів). Точна вартість розраховується після аналізу вимог до даних. За 5 років роботи ми реалізували понад 30 проектів з Core Data, включаючи високонавантажені додатки з синхронізацією через CloudKit. Якщо вам потрібна допомога з налаштуванням Core Data, отримайте консультацію.

Додаткові матеріали: офіційна документація Apple.

Наші компетенції:

Останні роботи

  • Розробка мобільного додатка для компанії FEEDME
    Розробка мобільного додатка для компанії FEEDME
    1009
  • Розробка мобільного додатку для компанії XOOMER
    Розробка мобільного додатку для компанії XOOMER
    902
  • Розробка мобільного додатку для компанії RHL
    Розробка мобільного додатку для компанії RHL
    1331
  • Розробка мобільного додатку для компанії ZIPPY
    Розробка мобільного додатку для компанії ZIPPY
    1179
  • Розробка мобільного додатку для компанії Affhome
    Розробка мобільного додатку для компанії Affhome
    1106
  • Розробка мобільного додатку для компанії FLAVORS
    Розробка мобільного додатку для компанії FLAVORS
    713