Ключевые моменты перед использованием SwiftData

от автора

На недавно завершившейся конференции Let’s Vision 2025 я получил множество вопросов о SwiftData: «Достаточно ли SwiftData развита, чтобы использовать ее в реальных проектах?» и „Как начинающему разработчику эффективно использовать SwiftData?“. Эти вопросы не только отражают живой интерес разработчиков к новейшему фреймворку Apple для хранения данных, но и свидетельствуют о нерешительности при выборе технологии.

Эта статья призвана стать руководством для разработчиков, заинтересованных в SwiftData, и помочь вам понять ее сильные стороны и ограничения, чтобы вы могли принимать обоснованные решения, исходя из потребностей вашего проекта. Независимо от того, рассматриваете ли вы возможность использования SwiftData в новом проекте или планируете переход с другого устоявшегося решения, приведённый ниже материал может помочь в процессе выбора.

Чем SwiftData отличается от фреймворков типа GRDB/SQLite.swift?

Несколько недель назад Point-Free выпустила библиотеку с открытым исходным кодом под названием SharingGRDB, которая значительно оптимизирует использование GRDB.swift в проектах SwiftUI. Это событие заставило некоторых разработчиков задуматься: если SharingGRDB настолько удобна, есть ли еще необходимость в использовании SwiftData?

На самом деле, основное отличие SwiftData/Core Data от таких инструментов, как GRDB.swift/SQLite.swift, заключается не в стиле или дизайне API, а в фундаментальных различиях в уровнях абстракции данных и организационных подходах.

SwiftData придерживается философии «данные — это объект». Ее модели данных легко интегрируются с парадигмой объектно-ориентированного программирования Swift и естественным образом сочетаются с декларативным стилем программирования SwiftUI. В отличие от них, такие инструменты, как GRDB и SQLite.swift, склоняются к идее «данные — это база данных», что делает их более подходящими для рабочих процессов разработки, ориентированных на базы данных.

Если вы являетесь разработчиком, хорошо знакомым с базами данных SQL, вы можете предпочесть такие инструменты, как GRDB. Они предоставляют вам большую автономию и гибкость, позволяя в полной мере использовать мощные возможности SQLite для организации и оптимизации данных. Концепции «таблиц», «столбцов» и «строк» могут показаться вам очень знакомыми, и вы, вероятно, привыкли отображать эти структуры баз данных непосредственно на свой Swift-код.

Однако если вы больше склоняетесь к объектно-ориентированному программированию или не хотите (или не должны) беспокоиться о базовых деталях сохранности данных, SwiftData — несомненно, лучший выбор. Он позволяет вам управлять объектами данных и их связями в манере, которая кажется почти родной для Swift, а такие специфические для баз данных понятия, как «таблицы», «столбцы» и «строки», автоматически абстрагируются фреймворком.

Помимо этих основных отличий, SwiftData/Core Data предлагает ряд преимуществ, с которыми трудно сравниться сторонним фреймворкам:

  • Бесшовная интеграция резервного копирования и синхронизации данных на базе iCloud бесплатно, что является почти стандартным требованием для разработчиков, создающих приложения в экосистеме Apple, особенно для небольших команд или независимых разработчиков.

  • Полная поддержка в качестве нативного системного фреймворка — в сценариях с ограниченными ресурсами, таких как виджеты или App Intents, и SwiftData, и Core Data работают без сбоев и поддерживают уведомления об изменении данных в реальном времени (достигается с помощью SwiftData History или Persistent History Tracking).

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

Сущности SwiftData — это не то же самое, что обычные объекты Swift

Apple предоставляет макрос @Model для SwiftData, чтобы упростить процесс моделирования данных. Во многих вводных учебниках подчеркивается его удобство, что приводит к тому, что некоторые новички ошибочно полагают, что построение моделей данных так же просто, как и работа с обычными объектами Swift. Однако, несмотря на то, что SwiftData стремится скрыть основные детали постоянства данных, она всё равно связана физическими ограничениями SQLite: в конечном итоге все типы данных будут преобразованы в форматы, поддерживаемые SQLite (SwiftData/Core Data еще не полностью использовали все поддерживаемые форматы данных SQLite).

При построении моделей данных с помощью SwiftData новичкам следует обратить внимание на следующее:

  • Предпочтительнее использовать базовые типы для свойств модели: Int, Double, Date, URL, String и т. д.

  • Выбирайте стабильные сложные типы: Для сложных типов, соответствующих Codable, старайтесь использовать те, которые широко распространены и имеют стабильный формат, например CGPoint или CLLocation.

  • Осторожно используйте пользовательские типы Codable: Избегайте прямого использования пользовательских типов Codable, если вы не уверены, что их не придется модифицировать в дальнейшем.

  • Использование перечислений: Перечисления с RawValue можно использовать напрямую.

  • Работа со сложными типами Codable: Для типов, которые ещё не доработаны или слишком сложны, рассмотрите возможность их ручного преобразования в базовые типы для хранения и использования вычисляемых свойств с целью упрощения операций чтения/записи.

  • Ограничения в сортировке и фильтрации: Свойства в типах Codable можно использовать для сортировки, но не для фильтрации. Если определенные свойства должны служить критериями фильтрации, рекомендуется абстрагировать их в отдельные сущности и связать с помощью отношений.

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

  • Избегайте назначения свойств отношений в инициализаторах: Поскольку в SwiftData используется модель, в которой сначала создаются объекты, а затем они вставляются в контекст, не назначайте свойства отношений непосредственно в инициализаторе модели.

Синхронизация данных

Одной из ключевых причин, по которой многие разработчики выбирают SwiftData/Core Data, является бесплатная интеграция резервного копирования и синхронизации данных на базе iCloud. В отличие от типичных сетевых решений для синхронизации данных, механизм синхронизации SwiftData имеет несколько отличительных особенностей:

  • Преимущественно локальное хранилище, с облачной синхронизацией в качестве дополнения

    Функция облачной синхронизации в SwiftData/Core Data — это дополнение, построенное поверх локального хранилища. В частности, Apple предоставляет автоматический механизм, который преобразует данные, сохраненные в SQLite с помощью SwiftData/Core Data, в формат, поддерживаемый CloudKit. Разработчики могут не использовать эту встроенную функциональность и вместо этого реализовать собственный механизм синхронизации с облаком. На самом деле, до того как Apple представила Core Data с CloudKit, многие разработчики использовали именно такой подход.

  • CloudKit не является базой данных реального времени

    Преобразование формата данных происходит асинхронно, и Apple динамически регулирует частоту синхронизации в зависимости от текущих условий на устройстве (таких как подключение к сети, уровень заряда батареи и пользовательские настройки синхронизации). Поэтому разработчикам не стоит приравнивать облачную синхронизацию SwiftData к производительности базы данных, работающей в режиме реального времени. На практике облачная синхронизация SwiftData больше похожа на синхронизацию в системных приложениях Apple (например, Фото или Заметки).

  • Аутентификация на основе iCloud: Преимущества и ограничения

    Облачная синхронизация SwiftData опирается на аутентификацию учётной записи iCloud, что означает, что пользователям не нужно отдельно входить в систему, чтобы синхронизировать данные на всех устройствах, использующих одну учётную запись iCloud. Однако это накладывает определенные ограничения: встроенная функция синхронизации жестко привязана к конкретной учетной записи iCloud. Если пользователь сменит учетную запись iCloud, локальные данные, связанные с первоначальной учетной записью, будут очищены и заменены данными из новой учетной записи. Поэтому разработчикам необходимо четко объяснить этот механизм, чтобы избежать недоразумений.

  • Особые требования к моделям при синхронизации

    Поскольку форматы данных CloudKit и SwiftData не полностью идентичны, при создании моделей SwiftData необходимо соблюдать определённые рекомендации, чтобы обеспечить совместимость локальных данных с облачными:

    • Избегайте использования ограничений уникальности: Не используйте @Attribute(.unique).

    • Убедитесь, что свойства optional или имеют значения по умолчанию: Все свойства должны быть либо optional, либо иметь значения по умолчанию.

    • Ограничения на правила удаления для отношений: Установка правила удаления отношения на Deny не поддерживается.

    • Отношения должны быть optional: Все свойства отношений должны быть определены как optional.

    После включения встроенной облачной синхронизации SwiftData любые изменения модели, нарушающие совместимость с лёгкой миграцией, будут запрещены. Разработчикам следует уточнить это с самого начала проекта.

  • Пользовательские механизмы синхронизации

    На самом деле многие системные приложения Apple сочетают SwiftData/Core Data с чистыми решениями CloudKit API. Такой подход является более гибким, чем встроенная функция синхронизации, и может удовлетворить более сложные потребности в синхронизации. Если вы обнаружили, что встроенная синхронизация SwiftData не отвечает вашим требованиям, но при этом хотите задействовать механизмы хранения и аутентификации iCloud, вы можете реализовать пользовательскую логику синхронизации с помощью CKSyncEngine. Однако такое решение, как правило, применимо к конкретным сценариям, не является универсальным и более сложно реализуемым.

    Если ваш проект требует синхронизации в реальном времени или высокой эффективности, вы можете рассмотреть возможность использования более эффективных решений для синхронизации от сторонних производителей, использования SwiftData исключительно для локального хранения данных или даже выбора таких фреймворков, как GRDB или SQLite.swift, вместо SwiftData.

Производительность

Как правило, производительность обратно пропорциональна уровню абстракции. Поскольку SwiftData обеспечивает более высокий уровень абстракции, его производительность чтения/записи данных заметно уступает фреймворкам, взаимодействующим напрямую с SQLite. С точки зрения чистой производительности чтения/записи данных рейтинг выглядит следующим образом: Фреймворки, работающие напрямую с SQLite > Core Data > SwiftData.

Однако, если учесть такие факторы, как эффективность разработки, автоматическое управление памятью и предполагаемые сценарии использования, SwiftData более чем способен справиться с требованиями основных мобильных и настольных приложений, учитывая современные аппаратные возможности.

Стоит также отметить, что SwiftData и Core Data используют один и тот же базовый формат хранения данных. Если SwiftData не удовлетворяет требованиям производительности для конкретного сценария, разработчики могут оптимизировать работу, интегрировав Core Data для таких задач, как пакетные операции или расширенные SQL-запросы, которые SwiftData пока не поддерживает.

Новичкам достаточно знать об этих путях оптимизации. Если вы не столкнулись с непреодолимым узким местом в производительности, обычно нет необходимости смешивать SwiftData и Core Data с самого начала. Хотя они используют один и тот же источник данных в бэкенде, одновременное использование обоих фреймворков сопряжено с определенными трудностями.

Функции

По сравнению с Core Data, SwiftData в настоящее время не хватает некоторых функциональных возможностей, в основном в следующих аспектах:

  • Неполная поддержка предикатов: не полностью поддерживает все функции предикатов, доступные в Core Data. Для частичной реализации расширенных запросов на основе SQL и динамического объединения предикатов требуются более высокие версии системы.

  • Ограниченная поддержка пакетных операций: Полноценные пакетные операции (такие как пакетное чтение и обновление) пока не поддерживаются.

  • Ограничения облачной синхронизации: Пока не поддерживаются такие функции, как публичные базы данных или обмен данными между различными учетными записями iCloud.

  • Отсутствует поддержка частичной синхронизации: Не поддерживается частичная синхронизация данных сущностей (когда данные одной и той же модели сущности могут храниться в разных постоянных хранилищах в Core Data).

Кроме того, учитывая цели разработки SwiftData, многие из элементов детального управления объектами данных и контекстами, доступных в Core Data, возможно, никогда не будут поддерживаться в SwiftData.

Тем не менее, текущая версия SwiftData способна удовлетворить требования большинства сценариев работы приложений.

Стабильность

Хотя SwiftData до сих пор выпустила только две основные версии, во второй версии (iOS 18) Apple внесла значительные внутренние изменения, некоторые из которых были даже разрушительными. Это иногда приводит к тому, что SwiftData работает менее стабильно на iOS 18 по сравнению с iOS 17. Помимо неконтролируемых факторов, таких как системные ошибки, следующие рекомендации могут помочь повысить стабильность ваших проектов SwiftData:

  • Предпочитайте использовать макрос @ModelActor: В SwiftData только PersistentIdentifier и ModelContainer соответствуют протоколу Sendable. Поэтому для реализации параллельных операций рекомендуется использовать макрос @ModelActor.

  • Избегайте назначения свойств отношений в инициализаторах: Поскольку SwiftData сначала создает объекты, а затем явно вставляет их в контекст, не назначайте свойства отношений в инициализаторе модели.

  • Абстрагируйте сложные свойства: Если свойство относится к типу Codable и должно использоваться для сортировки или фильтрации, подумайте о том, чтобы абстрагировать его в отдельную сущность и связать с ней через отношения.

  • Проблемы с обновлением представлений: В iOS 18 обновление данных с помощью @ModelActor не приводит к автоматическому обновлению представления (хотя операции удаления и добавления не затрагиваются). Для обновлений данных, которые должны быть отражены немедленно, рассмотрите возможность их выполнения в контексте представления.

В настоящее время наиболее оперативным каналом для получения отзывов и сообщений о проблемах с SwiftData являются официальные форумы разработчиков Apple. Рекомендуется подписаться на материалы, связанные с SwiftData, чтобы получать информацию об ошибках и соответствующих решениях сразу же после их появления.

Планируйте, прежде чем действовать

Кажущаяся «легкость в освоении и использовании» SwiftData может легко ввести новичков в заблуждение, заставив их поспешно внедрять её в производственные среды. Однако такие поспешные решения часто приводят к непредвиденным последствиям: только когда возникают проблемы с совместимостью или стабильностью, разработчики осознают, что их понимание фреймворка далеко от адекватного. Такой подход «запрыгивать на подножку» особенно опасен при выборе основополагающей инфраструктуры, например решений для постоянных данных.

В случае с такими базовыми фреймворками, как SwiftData, разумнее всего следовать принципу «планируй, прежде чем действовать» — тщательно разобраться в их возможностях и ограничениях, взвесить все «за» и «против» и проверить их целесообразность с помощью небольших экспериментов, прежде чем принимать окончательные технические решения. Такое осторожное отношение особенно важно сегодня, когда инструменты программирования с помощью искусственного интеллекта быстро распространяются, а эффективность генерации кода резко возрастает. В конце концов, технический долг может накапливаться гораздо быстрее, чем мы предполагаем.

SwiftData, являясь одним из наиболее важных решений для хранения данных в экосистеме Apple на ближайшее десятилетие, несомненно, заслуживает времени и сил разработчиков для глубокого изучения. Представляет собой не только новейшие разработки Apple в области работы с данными, но и в дальнейшем будет влиять на парадигмы разработки во всей экосистеме.


ссылка на оригинал статьи https://habr.com/ru/articles/890970/