Site iconSite icon AppTractor

Работаем с SwiftData в SwiftUI

На WWDC Apple анонсировала новый фреймворк для работы с данными, обертку вокруг CoreDataSwiftData. Он позволяет быстро добавить персистентность в ваше приложение, с минимальным количеством кода и без внешних зависимостей.

Вы можете использовать SwiftData для сохранения данных вашего приложения для офлайн использования или для кэширования временных данных. Фреймворк полностью сфокусирован на коде, без внешних форматов файлов, и использует новую систему макросов Swift для бесшовной работы с API.

Создание модели

@Model — это макрос, который помогает определить схему вашей модели.

Нам нужно добавить макрос Model перед объявлением вашего класса, чтобы преобразовать Swift-класс в хранимую модель, управляемую SwiftData.

@Model
class User {
    var id: UUID
    var firstName: String
    var lastName: String
    var company: Company
    
    init(firstName: String, lastName: String, company: Company) {
        self.id = UUID()
        self.firstName = firstName
        self.lastName = lastName
        self.company = company
    }
}

@Model
class Company {
    var id: UUID
    var companyName: String
    var designation: String
    
    init(companyName: String, designation: String) {
        self.id = UUID()
        self.companyName = companyName
        self.designation = designation
    }
}

Контейнер модели

Это объект, управляющий схемой и конфигурацией хранилища моделей.

Контейнер моделей устанавливается в WindowGroup. Мы можем передавать туда несколько моделей данных.

@main
struct SwiftData_ExampleApp: App {
    var body: some Scene {
        WindowGroup {
            NavigationStack {
                UserList()
            }
        }
        .modelContainer(for: [User.self, Company.self])
    }
}

Контекст модели

ModelContext — это объект, позволяющий извлекать, вставлять и удалять модели, а также сохранять любые изменения на диске.

Все в SwiftData происходит с контекстом модели. По сути, объект похож на контекст представления в CoreData.

@Environment(\.modelContext) private var modelContext

Запрос

Используйте @Query в представлениях SwiftUI для получения данных.

SwiftData и SwiftUI работают вместе, чтобы обеспечить живое обновление ваших представлений при изменении базовых данных, без необходимости вручную обновлять результаты.

Вы можете добавить predicate к запросу для фильтрации элементов, sort для сортировки, установить order — сортировать в прямом или обратном порядке, а также задать animation для изменений пользовательского интерфейса, которые происходят в результате изменения полученных результатов.

@Query(sort: \User.firstName, order: .forward, animation: .smooth) var users: [User]

Ниже приведен пример получения пользователей и отображения их в списке:

struct UserList: View {
    @Environment(\.modelContext) private var modelContext
    @Query(sort: \User.firstName, order: .forward, animation: .smooth) var users: [User]
    
    var body: some View {
        VStack {
            if users.isEmpty {
               Text("Press '+' to add new user")
            } else {
                List(users) { user in
                    NavigationLink {
                        EditUser(user: user)
                    } label: {
                        VStack(alignment: .leading) {
                            Text("\(user.firstName) \(user.lastName)")
                                .fontWeight(.bold)
                                .font(.headline)
                            Text("Company: \(user.company.companyName)")
                                .fontWeight(.regular)
                                .font(.caption)
                            Text("Designation: \(user.company.designation)")
                                .fontWeight(.regular)
                                .font(.caption2)
                        }
                        .swipeActions {
                            Button("Delete", role: .destructive) {
                                modelContext.delete(user)
                            }
                        }
                    }
                }
            }
        }
        .toolbar {
            NavigationLink {
                CreateUser()
            } label: {
                Text("+")
                    .fontWeight(.bold)
                    .font(.title)
            }
        }
    }
}

Вставка, обновление и удаление данных с использованием контекста.

Нам не нужно явно вызывать сохранение явно, SwiftData автоматически сохраняет modelcontext.

//insert
let user = User(firstName: firstName, lastName: lastName, company: Company(companyName: companyName, designation: designation))
modelContext.insert(user)

//update
user.lastName = "Something"

//delete
modelContext.delete(user)

Ниже приведен пример вставки объекта в SwiftData:

struct CreateUser: View {
    @Environment(\.modelContext) private var modelContext
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    @State private var firstName: String = ""
    @State private var lastName: String = ""
    @State private var companyName: String = ""
    @State private var designation: String = ""
    
    var body: some View {
        VStack(spacing: 20) {
            TextField("First Name", text: $firstName)
                .textFieldStyle(.roundedBorder)
            TextField("Last Name", text: $lastName)
                .textFieldStyle(.roundedBorder)
            TextField("Company Name", text: $companyName)
                .textFieldStyle(.roundedBorder)
            TextField("Designation", text: $designation)
                .textFieldStyle(.roundedBorder)
            Spacer()
        }
        .padding(20)
        .navigationTitle("Create User")
        .toolbar {
            Button(action: {
                let user = User(firstName: firstName, lastName: lastName, company: Company(companyName: companyName, designation: designation))
                modelContext.insert(user)
                do {
                    try modelContext.save()
                    presentationMode.wrappedValue.dismiss()
                } catch {
                    print(error.localizedDescription)
                }
            }, label: {
                Text("Save")
            })
        }
    }
}

Ключевые моменты SwiftData

Еще про SwiftData

Источник

Exit mobile version