CoreData + SwiftUI

May 01 2023
Qui puoi vedere l'articolo originale Recentemente ho dovuto creare un'app utilizzando SwiftUI e CoreData. Pensavo che CoreData fosse usato quasi come lo useresti con UIKit, ma a quanto pare ci sono alcune differenze.
Foto di Michael Dziedzic su Unsplash

Qui potete vedere l'articolo originale

Di recente ho dovuto creare un'app utilizzando SwiftUI e CoreData .

Pensavo che CoreData fosse usato quasi come lo useresti con UIKit, ma a quanto pare ci sono alcune differenze.

Questa guida vuole essere un riassunto della mia esperienza nell'utilizzo di CoreData in combinazione con SwiftUI. Se troverò altri aspetti, li aggiungerò a questa guida.

Quindi, senza ulteriori indugi, iniziamo.

Impostare

Questa è una parte piuttosto semplice.

  • Se avvii un nuovo progetto puoi selezionare l'opzione ' Usa dati di base ' e ' Ospita in CloudKit ' se vuoi salvare i dati degli utenti nel cloud. In questo caso XCode si occuperà di impostare il progetto per te. (Per la parte CloudKit sarà necessario eseguire alcuni passaggi aggiuntivi).
  • Se hai già un progetto dovrai creare un file Persistence.swift e un file swift in cui inizializzare lo stack CoreData. (Puoi persino creare un nuovo progetto seguendo il passaggio precedente e copiare il file Persistence.swift generato da XCode nel tuo progetto.

Ora che hai il tuo progetto, per poter utilizzare CoreData all'interno delle tue viste, devi passare la managedObjectContextgerarchia di visualizzazione inferiore.

Di solito questo viene fatto nel tuo file [appname]App.swift .

PersistenceController ( ecco un esempio ) è la struct che XCode genera automaticamente per te quando avvii un nuovo progetto con l'opzione 'Use Core Data' selezionata.

@main
struct ExampleApp: App {

  let persistenceController = PersistenceController.shared

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

Fantastico, ora puoi creare, leggere, aggiornare ed eliminare NSManagedObjects nelle tue visualizzazioni.

Operare con CoreData

Per operare con CoreData è necessario accedere a NSManagedObjectContext. Per farlo, hai due opzioni:

  • Usando il wrapper @ Environment nelle tue viste
  • @Environment(\.managedObjectContext) private var viewContext
    

    @EnvironmentObject private var persistenceController: PersistenceController
    

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

Per salvare un NSManagedObject devi prima istanziarlo e poi configurarne le proprietà. E poi salva il contesto.

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

Recupero di oggetti

Ora la parte interessante, è qui che ho trovato le maggiori difficoltà. Cominciamo subito.

Per recuperare oggetti in SwiftUI il modo più conveniente per farlo è usare i wrapper @FetchRequest o @SectionedFetchRequest , in ogni singola View che devi leggere da CoreData.

Il passaggio di oggetti recuperati tra le viste interromperà gli aggiornamenti automatici nel caso in cui aggiungi, modifichi o elimini oggetti. (Se conosci un modo per passare gli oggetti di recupero senza interrompere gli aggiornamenti fammelo sapere e aggiornerò questa guida)

Quindi è necessario aggiungere un @FetchRequest in ogni vista di cui hai bisogno di oggetti CoreData e aggiornamenti automatici. So che è un po' fastidioso ma ne varrà la pena.

Quindi, detto questo, il codice è il seguente:

@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
    }
  }
}

Utilizzando @FetchRequest o @SectionedFetchRequest ogni volta che aggiungi, aggiorni o elimini un oggetto, le viste vengono aggiornate automaticamente.

Ora, se hai bisogno di utilizzare un @FetchRequest con un NSPredicate che ha un parametro passato dalla vista genitore, ho scoperto che l'opzione successiva funziona meravigliosamente.

@FetchRequest
var objects: FetchedResults<Object>

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

Aggiornamento degli oggetti

Per aggiornare un file NSManagedObjectdovrai NSManagedObjectaggiornare, recuperare come descritto in precedenza e aggiornarne le proprietà. E poi salva il contesto.

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

Per eliminare un NSManagedObjectfile dovrai NSManagedObjectaggiornare, recuperare come descritto in precedenza ed eliminarlo.

viewContext.delete(object)

Conclusione

Questo è tutto ciò che ho scoperto finora su CoreData utilizzato con SwiftUI. Questa guida sarà costantemente aggiornata.

Se vuoi suggerire un modo migliore di fare qualcosa, lascia un commento e aggiornerò questa guida con l'opzione migliore.

Spero di averti aiutato nel tuo viaggio con SwiftUI e lo sviluppo iOS.

LASCIA UN CLAP se ti è piaciuto questo articolo lo apprezzo molto.

Ci vediamo nella prossima guida!

Se desideri supportare il mio lavoro e vedere questa guida in azione, dai un'occhiata a BrainDump — Notes & Writing .

Grazie