CoreData + SwiftUI

May 01 2023
Здесь вы можете увидеть оригинальную статью Недавно мне пришлось создать приложение с использованием SwiftUI и CoreData. Я думал, что CoreData используется почти так же, как вы использовали бы его с UIKit, но, видимо, есть некоторые отличия.
Фото Майкла Дзидзича на Unsplash

Здесь вы можете увидеть оригинал статьи

Недавно мне пришлось создать приложение с использованием SwiftUI и CoreData .

Я думал, что CoreData используется почти так же, как вы использовали бы его с UIKit, но, видимо, есть некоторые отличия.

Это руководство предназначено для обобщения моего опыта использования CoreData в сочетании со SwiftUI. Если я найду другие аспекты, я добавлю их в этот гайд.

Итак, без лишних слов, приступим.

Настраивать

Это довольно простая часть.

  • Если вы начинаете новый проект, вы можете установить флажок « Использовать основные данные » и « Разместить в CloudKit », если хотите сохранить данные своих пользователей в облаке. В этом случае XCode позаботится о настройке проекта за вас. (Для части CloudKit нужно будет сделать несколько дополнительных шагов).
  • Если у вас уже есть проект, вам нужно создать файл Persistence.swift и файл swift, в котором вы инициализируете стек CoreData. (Вы даже можете создать новый проект, следуя предыдущему шагу, и скопировать файл Persistence.swift , сгенерированный XCode, в свой проект.

Теперь, когда у вас есть проект, чтобы иметь возможность использовать CoreData в своих представлениях, вам нужно передать managedObjectContextвниз иерархию представлений.

Обычно это делается в файле [appname]App.swift .

PersistenceController ( вот пример ) — это структура, которую XCode автоматически генерирует для вас, когда вы начинаете новый проект с отмеченным параметром «Использовать основные данные».

@main
struct ExampleApp: App {

  let persistenceController = PersistenceController.shared

  var body: some Scene {
    WindowGroup {
      ContentView()
        .environmentObject(persistenceController)
        .environment(\.managedObjectContext, persistenceController.container.viewContext)
    }
  }
}

Отлично, теперь вы можете создавать, читать, обновлять и удалять NSManagedObjects в своих представлениях.

Работа с CoreData

Для работы с CoreData вам необходимо получить доступ к NSManagedObjectContext. Для этого у вас есть два варианта:

  • Использование оболочки @Environment в ваших представлениях
  • @Environment(\.managedObjectContext) private var viewContext
    

    @EnvironmentObject private var persistenceController: PersistenceController
    

do {
  if container.viewContext.hasChanges {
    try container.viewContext.save()
  }
} catch {
  print(error)
}

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

let note = Note(context: container.viewContext)
note.id = id
note.text = text
note.folder = folder
note.creationDate = Date()
saveContext()

Получение объектов

Теперь часть извлечения, здесь я столкнулся с наибольшими трудностями. Давайте начнем прямо сейчас.

Для извлечения объектов в SwiftUI наиболее удобным способом является использование оболочек @FetchRequest или @SectionedFetchRequest в каждом отдельном представлении, которое вам нужно прочитать из CoreData.

Передача выбранных объектов между представлениями нарушит автоматическое обновление, если вы добавляете, редактируете или удаляете объекты. (Если вы знаете способ передачи объектов без прерывания обновлений, дайте мне знать, и я обновлю это руководство)

Поэтому вам нужно добавить @FetchRequest в каждое представление, в котором вам нужны объекты CoreData и автоматические обновления. Я знаю, что это немного раздражает, но оно того стоит.

Итак, с учетом сказанного код выглядит следующим образом:

@FetchRequest(entity: \Object.type,
              sortDescriptors: [NSSortDescriptor],
              predicate: NSPredicate,
              animation: .default)
var objects: [Object]

@SectionedFetchRequest(entity: \Object.type,
                         sectionIdentifier: \Object.property,
                         sortDescriptors: [NSSortDescriptor],
                         predicate: NSPredicate,
                         animation: .default)
var sections: SectionedFetchResults<YourSectionType, Object>

List(sections) { section in
  Section(section.id) {
    ForEach(section) { object in
      // Configure your view with the object
    }
  }
}

Используя @FetchRequest или @SectionedFetchRequest , где бы вы ни добавляли, обновляли или удаляли объект, представления автоматически обновлялись.

Теперь, если вам нужно использовать @FetchRequest с NSPredicate , у которого есть параметр, переданный из родительского представления, я обнаружил, что следующий вариант прекрасно работает.

@FetchRequest
var objects: FetchedResults<Object>

init(id: ID) {
  _objects = FetchRequest<Object>(predicate: NSPredicate(format: "id == %@", id))
}

Обновление объектов

Чтобы обновить a, NSManagedObjectвам нужно будет получить файл NSManagedObjectto update, полученный, как описано выше, и обновить его свойства. А затем сохраните контекст.

note.text = newText
note.folder = newFolder
saveContext()

Чтобы удалить файл, NSManagedObjectвам нужно будет NSManagedObjectобновить его, как описано выше, и удалить его.

viewContext.delete(object)

Заключение

Это все, что я пока обнаружил о CoreData, используемом со SwiftUI. Это руководство будет постоянно обновляться.

Если вы хотите предложить лучший способ сделать что-то, оставьте комментарий , и я обновлю это руководство лучшим вариантом.

Я надеюсь, что помог вам в вашем путешествии с SwiftUI и разработкой iOS.

ПОСТАВЬТЕ ХЛОП, если вам понравилась эта статья, я очень ценю это.

Увидимся в следующем руководстве!

Если вы хотите поддержать мою работу и увидеть это руководство в действии, ознакомьтесь с BrainDump — Notes & Writing .

Спасибо