Хранение данных со SwiftData
Чтобы данные пережили перезапуск приложения, их нужно сохранять. SwiftData — современный фреймворк хранения от Apple (iOS 17+), пришедший на смену Core Data.
Суть урока: пометьте класс макросом @Model — и он станет сохраняемой моделью. @Query автоматически подтягивает данные из хранилища во вью и обновляет список при любых изменениях.
SwiftData, представленная в iOS 17, делает персистентность почти бесшовной. Модель — это обычный класс с макросом @Model; макрос превращает его в сущность, которую можно сохранять в базу:
import SwiftData
@Model
class TodoItem {
var title: String
var isDone: Bool
var createdAt: Date
init(title: String) {
self.title = title
self.isDone = false
self.createdAt = .now
}
}Чтобы показать сохранённые данные во вью, используют макрос @Query — он загружает объекты и автоматически обновляет интерфейс при изменениях в хранилище. Доступ к операциям записи даёт ModelContext из окружения:
struct TodoListView: View {
@Query(sort: \.createdAt) private var items: [TodoItem]
@Environment(\.modelContext) private var context
var body: some View {
List {
ForEach(items) { item in
Text(item.title)
}
.onDelete { offsets in
for i in offsets { context.delete(items[i]) }
}
}
.toolbar {
Button("Добавить") {
context.insert(TodoItem(title: "Новая задача"))
}
}
}
}Заметьте: вы не пишете SQL и не управляете сохранением вручную. Вставили объект через context.insert — и @Query сам обновит список. SwiftData спроектирована заодно со SwiftUI: изменения в данных мгновенно отражаются на экране. Контейнер хранилища подключается на старте приложения модификатором .modelContainer(for: TodoItem.self).
@Model class TodoItem (описание сущности)
|
ModelContext (вставка / удаление / сохранение)
|
Хранилище на диске (под капотом — Core Data)
|
@Query private var items (живой запрос)
|
List / ForEach (UI обновляется сам)Попробуй сам ▶ — запусти код прямо в браузере (Pyodide). Здесь нет Swift, но логика та же, что под капотом мобильного кода:
# Имитируем @Query + ModelContext: живой список, реагирующий на изменения.
store = [] # "хранилище на диске"
def insert(title):
store.append({'title': title, 'done': False})
def delete(index):
if 0 <= index < len(store):
store.pop(index)
def query_sorted(): # как @Query(sort:)
return sorted(store, key=lambda x: x['title'])
insert('Купить молоко')
insert('Учить SwiftData')
insert('Опубликовать приложение')
print('Список:', [t['title'] for t in query_sorted()])
delete(0)
print('После удаления:', [t['title'] for t in query_sorted()])Как работает под капотом
Макрос @Model на этапе компиляции добавляет классу инфраструктуру персистентности — фактически SwiftData построена поверх проверенной временем Core Data. ModelContext — это рабочая область: он отслеживает изменения объектов и по команде save (часто автоматической) записывает их в хранилище. @Query — это живой запрос: он подписан на контекст и при любом изменении пересчитывается, заставляя SwiftUI перерисовать список. Так данные, хранилище и интерфейс остаются согласованными.
Частые ошибки
- Забыть подключить .modelContainer. Без контейнера @Query и context не будут работать.
- Хранить @Model-объекты как обычные структуры. Это классы со своей идентичностью и жизненным циклом.
- Целиться в iOS 16 и ниже. SwiftData требует iOS 17+; для более старых версий нужна Core Data.
Best practices
- Используйте @Query для отображения и ModelContext для вставки/удаления.
- Подключайте .modelContainer один раз на уровне приложения.
- Задавайте сортировку и фильтры прямо в @Query, а не в коде вью.
Итоги. SwiftData — современный, тесно интегрированный со SwiftUI способ хранить данные. @Model описывает сущность, ModelContext управляет записью, а @Query живо отражает хранилище в интерфейсе. Этим уроком мы замыкаем путь от языка до готового приложения с данными, навигацией и сетью.
Шире контекста
SwiftData завершает картину современного стека Apple: язык Swift, интерфейс SwiftUI, конкурентность async/await и теперь персистентность, спроектированная заодно со всем остальным. Под капотом она опирается на проверенную годами Core Data, но прячет её многословность за чистыми макросами @Model и @Query. Эта тесная интеграция означает, что данные, хранилище и интерфейс остаются в согласии без ручной синхронизации: вставили объект — список обновился сам. По мере роста приложения вы столкнётесь с более сложными темами — связями между сущностями, миграциями схемы при обновлении модели, фильтрацией и сортировкой через предикаты, синхронизацией через iCloud. Но фундамент останется тем же простым и декларативным. Важная практическая оговорка: SwiftData требует iOS 17 и новее, поэтому для приложений, поддерживающих более старые версии, по-прежнему актуальна Core Data, и часто их используют бок о бок в переходный период. Завершив этот урок, вы прошли полный путь — от первой переменной до приложения, которое загружает, отображает и сохраняет данные.