Données de base et Swift: suppressions par lots

Core Data est un framework avec lequel j’aime beaucoup travailler. Même si Core Data n’est pas parfait, c’est formidable de voir qu’Apple continue d’investir dans le framework. Cette année, par exemple, Apple a ajouté la possibilité de supprimer des enregistrements par lots. Dans l’article précédent, nous avons discuté des mises à jour par lots. L’idée sous-jacente aux suppressions par lots est très similaire, comme vous l’apprendrez dans ce didacticiel.

1. Le problème

Si une application Core Data doit supprimer un grand nombre d’enregistrements, elle est confrontée à un problème. Même s’il n’est pas nécessaire de charger un enregistrement en mémoire pour le supprimer, c’est simplement ainsi que fonctionne Core Data. Comme nous l’avons mentionné dans l’article précédent, cela présente un certain nombre d’inconvénients. Avant l’introduction des mises à jour par lots, il n’existait pas de solution appropriée pour mettre à jour un grand nombre d’enregistrements. Avant iOS 9 et OS X El Capitan, il en était de même pour les suppressions par lots.

2. La solution

Tandis que le NSBatchUpdateRequest classe a été introduite dans iOS 8 et OS X Yosemite, la NSBatchDeleteRequest La classe n’a été ajoutée que récemment, parallèlement à la sortie d’iOS 9 et d’OS X El Capitan. Comme son cousin, NSBatchUpdateRequest, une NSBatchDeleteRequest l’instance fonctionne directement sur un ou plusieurs magasins persistants.

Malheureusement, cela signifie que les suppressions par lots souffrent des mêmes limitations que les mises à jour par lots. Étant donné qu’une demande de suppression par lot affecte directement un magasin persistant, le contexte de l’objet géré ignore les conséquences d’une demande de suppression par lot. Cela signifie également qu’aucune validation n’est effectuée et qu’aucune notification n’est publiée lorsque les données sous-jacentes d’un objet géré changent à la suite d’une demande de suppression par lots. Malgré ces limitations, les règles de suppression des relations sont appliquées par Core Data.

3. Comment ça marche?

Dans le didacticiel précédent, nous avons ajouté une fonctionnalité pour marquer chaque tâche comme terminée. Revoyons cette application et ajoutons la possibilité de supprimer toutes les tâches marquées comme terminées.

Étape 1: configuration du projet

Téléchargez ou clonez le projet à partir de GitHub et ouvrez-le dans Xcode 7.Assurez-vous que la cible de déploiement du projet est définie sur iOS 9 ou supérieur pour vous assurer que le NSBatchDeleteRequest la classe est disponible.

Étape 2: Créer un élément de bouton de barre

Ouvert ViewController.swift et déclarer une propriété deleteAllButton de type UIBarButtonItem. Vous pouvez supprimer le checkAllButton propriété car nous n’en aurons pas besoin dans ce tutoriel.

Initialisez l’élément de bouton de barre dans le viewDidLoad() méthode de la ViewController class et définissez-le comme élément du bouton de la barre de gauche de l’élément de navigation.

Étape 3: mettre en œuvre deleteAll(_:) Méthode

En utilisant le NSBatchDeleteRequest class n’est pas difficile, mais nous devons nous occuper de quelques problèmes inhérents au fonctionnement direct sur un magasin persistant.

Créer une demande de récupération

Un NSBatchDeleteRequest l’objet est initialisé avec un NSFetchRequest objet. C’est cette demande d’extraction qui détermine quels enregistrements seront supprimés du ou des magasins persistants. Dans deleteAll(_:), nous créons une demande de récupération pour le Article entité. Nous définissons les demandes de récupération predicate propriété pour nous assurer que nous supprimons uniquement Article enregistrements marqués comme terminés.

Parce que la demande de récupération détermine quels enregistrements seront supprimés, nous avons toute la puissance du NSFetchRequest classe à notre disposition, y compris la définition d’une limite sur le nombre d’enregistrements, l’utilisation de descripteurs de tri et la spécification d’un décalage pour la demande de récupération.

En relation :  5 correctifs simples pour les problèmes courants de Google Play Store

Créer une demande de lot

Comme je l’ai mentionné précédemment, la demande de suppression par lots est initialisée avec un NSFetchRequest exemple. Parce que le NSBatchDeleteRequest la classe est une NSPersistentStoreRequest sous-classe, nous pouvons définir la demande resultType propriété pour spécifier le type de résultat qui nous intéresse.

le resultType propriété d’un NSBatchDeleteRequest l’instance est de type NSBatchDeleteRequestResultType.Le NSBatchDeleteRequestResultType enum définit trois variables membres:

  • ResultTypeStatusOnly: Cela nous indique si la demande de suppression par lots a réussi ou échoué.
  • ResultTypeObjectIDs: Cela nous donne un tableau des NSManagedObjectID instances qui correspondent aux enregistrements supprimés par la demande de suppression par lots.
  • ResultTypeCount: En définissant la demande resultType propriété à ResultTypeCount, on nous donne le nombre d’enregistrements qui ont été affectés (supprimés) par la demande de suppression par lots.

Exécuter la demande de mise à jour par lots

Vous vous souvenez peut-être du didacticiel précédent que executeRequest(_:) est une méthode de lancer. Cela signifie que nous devons encapsuler l’appel de méthode dans un do-catch déclaration. le executeRequest(_:) méthode renvoie un NSPersistentStoreResult objet. Comme nous traitons une demande de suppression par lots, nous convertissons le résultat en un NSBatchDeleteResult objet. Le résultat est imprimé sur la console.

Si vous deviez exécuter l’application, remplissez-la avec quelques éléments et appuyez sur le bouton Tout supprimer bouton, l’interface utilisateur ne serait pas mise à jour. Je peux vous assurer que la demande de suppression par lots a bien fonctionné. N’oubliez pas que le contexte de l’objet géré n’est en aucun cas notifié des conséquences de la demande de suppression par lots. De toute évidence, c’est quelque chose que nous devons corriger.

Mise à jour du contexte de l’objet géré

Dans le tutoriel précédent, nous avons travaillé avec le NSBatchUpdateRequest classe. Nous avons mis à jour le contexte d’objet géré en actualisant les objets dans le contexte d’objet géré qui ont été affectés par la demande de mise à jour par lots.

Nous ne pouvons pas utiliser la même technique pour la demande de suppression par lots, car certains objets ne sont plus représentés par un enregistrement dans le magasin persistant. Nous devons prendre des mesures drastiques comme vous pouvez le voir ci-dessous. Nous appelons reset() sur le contexte d’objet géré, ce qui signifie que le contexte d’objet géré commence par une table rase.

En relation :  SpaceTalk: une montre pour enfant pour la confidentialité

Cela signifie également que le contrôleur des résultats récupérés doit effectuer une extraction pour mettre à jour les enregistrements qu’il gère pour nous. Pour mettre à jour l’interface utilisateur, nous invoquons reloadData() sur la vue de la table.

4. Enregistrer l’état avant la suppression

Il est important d’être prudent chaque fois que vous interagissez directement avec un ou plusieurs magasins persistants. Plus tôt dans cette série, j’ai écrit qu’il n’est pas nécessaire d’enregistrer les modifications d’un contexte d’objet géré chaque fois que vous ajoutez, mettez à jour ou supprimez un enregistrement. Cette affirmation est toujours vraie, mais elle a également des conséquences lorsque vous travaillez avec NSPersistentStoreRequest sous-classes.

Avant de continuer, j’aimerais amorcer le magasin persistant avec des données factices afin que nous ayons quelque chose avec quoi travailler. Cela facilite la visualisation de ce que je suis sur le point d’expliquer. Ajoutez la méthode d’assistance suivante à ViewController.swift et invoquez-le dans viewDidLoad().

Dans seedPersistentStore(), nous créons quelques enregistrements et marquons chaque troisième élément comme terminé. Notez que nous appelons save() sur le contexte d’objet géré à la fin de cette méthode pour vous assurer que les modifications sont transmises au magasin persistant. Dans viewDidLoad(), nous semons le magasin persistant.

Exécutez l’application et appuyez sur le Tout supprimer bouton. Les enregistrements marqués comme terminés doivent être supprimés. Que se passe-t-il si vous marquez quelques-uns des éléments restants comme terminés et appuyez sur le Tout supprimer bouton à nouveau. Ces éléments sont-ils également supprimés? Pouvez-vous deviner pourquoi?

La demande de suppression par lots interagit directement avec le magasin persistant. Cependant, lorsqu’un élément est marqué comme terminé, la modification n’est pas immédiatement transmise au magasin persistant. Nous n’appelons pas save() sur le contexte de l’objet géré chaque fois que l’utilisateur marque un élément comme terminé. Nous ne le faisons que lorsque l’application est poussée en arrière-plan et lorsqu’elle est arrêtée (voir AppDelegate.swift).

La solution est simple. Pour résoudre le problème, nous devons enregistrer les modifications du contexte de l’objet géré avant d’exécuter la demande de suppression par lots. Ajoutez les lignes suivantes au deleteAll(_:) et réexécutez l’application pour tester la solution.

Conclusion

le NSPersistentStoreRequest Les sous-classes sont un ajout très utile au framework Core Data, mais j’espère qu’il est clair qu’elles ne devraient être utilisées qu’en cas d’absolue nécessité. Apple n’a ajouté que la possibilité d’opérer directement sur les magasins persistants pour corriger les faiblesses du framework, mais le conseil est de les utiliser avec parcimonie.

Moyens Staff
Moyens I/O Staff vous a motivé, donner des conseils sur la technologie, le développement personnel, le style de vie et des stratégies qui vous aider.