Commencer avec Core Data! Difficile avec des mots simples [Partie 2]

Dans cet article, je voudrais révéler davantage les capacités de Core Data. Cet article est une continuation . J'espère vraiment que je pourrai avoir l'idée que Core Data n'est pas l'une des nombreuses bases de données relationnelles, mais un outil très puissant qui peut devenir une arme intégrale dans l'arsenal de tout développeur IOS qui se respecte.

Eh bien, commençons!

Aujourd'hui, nous envisageons de travailler avec deux NSManageObjectContext et NSFetchedResultsController.

Deux NSManageObjectContext et pourquoi est-ce nécessaire?


Si votre application utilise activement une API via laquelle elle reçoit des données et que vous souhaitez enregistrer ces données quelque part, Core Data est un excellent choix. Quels problèmes pourriez-vous rencontrer avec cela? Le premier et le plus évident - la quantité de données sera si grande que lorsque vous essayez de les enregistrer, notre application se fige pendant un certain temps, ce qui affectera l'expérience de l'utilisateur. Un GCD ordinaire ne peut être supprimé car il est indépendant, notre Core Data Stack, qui a été mentionné ici , fonctionne de manière synchrone et pour tout accès à notre NSManageObjectContext, nous devons attendre la fin de la boucle.

Mais ici, le NSManageObjectContext privé qui fonctionne dans le thread d'arrière-plan vient à la rescousse. Pour l'appeler, vous devez d'abord contacter notre NSPersistentContainer.

L'initialisation ressemblera à ceci:

lazy var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "Preset")
    container.loadPersistentStores { (persistent, error) in
        if let error = error {
            fatalError("Error: " + error.localizedDescription)
        }
    }
    container.viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
    container.viewContext.shouldDeleteInaccessibleFaults = true
    container.viewContext.automaticallyMergesChangesFromParent = true
    return container
}()

Mergepolicy


Ici, vous spécifiez la politique de fusion de notre NSManageObjectContext. Ici, nous indiquons explicitement comment les données de base doivent se comporter en cas de conflit de données.

Options MergePolicy:

  1. NSRollbackMergePolicy - En cas de conflit, ignore toutes les modifications jusqu'à ce qu'elles se produisent
  2. NSOverwriteMergePolicy - Enregistre de nouvelles valeurs indépendamment des données
  3. NSMergeByPropertyStoreTrumpMergePolicy - Enregistre les objets modifiés propriété par propriété, dans ce cas, les données enregistrées prévaudront
  4. NSMergeByPropertyObjectTrumpMergePolicy - Enregistre les objets modifiés propriété par propriété, dans ce cas, les nouvelles données prévaudront

AutomaticallyMergesChangesFromParent - indique si notre contexte fusionnera automatiquement les données.
Ensuite, créez un nouveau contexte:

let context = persistentContainer.viewContext
let context = persistentContainer.newBackgroundContext()

Nous avons maintenant deux NSManageObjectContext. Le premier sert à travailler avec l'interface utilisateur et s'exécute sur le thread principal, et le second a privateQueueConcurrencyType pour travailler en arrière-plan.

Nous l'utiliserons pour télécharger des données.

let object = NSEntityDescription.insertNewObject(forEntityName: "Name", into: context)
saveChanges(with: context)

Ici, nous créons notre entité, puis nous pouvons lui attribuer les propriétés nécessaires, après quoi nous appelons la méthode save, elle ressemble à ceci:

func saveChanges(with context: NSManagedObjectContext) {
        context.performAndWait {
            if context.hasChanges {
                do {
                    try context.save()
                } catch {
                    context.rollback()
                }
            }
            context.reset()
        }
    }

Vous avez le choix entre 2 méthodes:

  • performAndWait - effectue des actions sur le thread de contexte de manière synchrone
  • effectuer - effectue des actions sur le flux de contexte de manière asynchrone


NSFetchedResultsController


NSFetchedResultsController - un contrôleur qui exécute certaines demandes et affiche les données nécessaires à l'utilisateur.

lazy var fetchedResultsController: NSFetchedResultsController<Pack> = {
        let fetchRequest = NSFetchRequest<Pack>(entityName:"Pack")
        fetchRequest.fetchBatchSize = 20
        fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending:true)]
        let controller = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)

        controller.delegate = self
        do {
            try controller.performFetch()
        } catch {
            print(error.localizedDescription)
        }
        return controller
    }()

NSFetchedResultsController a un très grand nombre de configurations, nous allons en analyser quelques-unes:

Fetchlimit
FetchLimit —

Sketchoffset
FetchOffset — . 2, .

FetchbatchSize
FetchBatchSize — . Table/CollectionView 5 , 7 , .

FetchbatchSize
FetchBatchSize — .

SortDescriptor
SortDescriptor — , .

ReturnsObjectsAsFaults
ReturnsObjectsAsFaults — , , , PersistentStore RawCache

Pour le moment, nous avons un NSFetchedResultsController qui devrait afficher nos données dans un tableau. Pour mettre à jour les données, vous devez appeler la méthode déléguée:

extension ViewController: NSFetchedResultsControllerDelegate {
    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
       collectionView.reloadData()
    }
}

Cette méthode déléguée fonctionne lorsque nous avons des changements dans notre contexte. Dans cette implémentation, cela se produit après avoir enregistré les données dans un privateContext. À ce moment, la méthode déléguée est déclenchée et les données sont mises à jour.

Juste quelques actions et Core Data d'une base de données régulière se transforment en une arme puissante de tout développeur iOS.

Bon codage!

All Articles