Beginnend mit Kerndaten! In einfachen Worten schwierig [Teil 2]

In diesem Artikel möchte ich die Funktionen von Core Data näher erläutern. Dieser Artikel ist eine Fortsetzung . Ich hoffe wirklich, dass ich auf die Idee kommen kann, dass Core Data keine der vielen relationalen Datenbanken ist, sondern ein sehr leistungsfähiges Werkzeug, das zu einer integralen Waffe im Arsenal eines jeden sich selbst respektierenden IOS-Entwicklers werden kann.

Nun, fangen wir an!

Heute schauen wir uns die Arbeit mit zwei NSManageObjectContext und NSFetchedResultsController an.

Zwei NSManageObjectContext und warum wird das benötigt?


Wenn Ihre Anwendung aktiv eine API verwendet, über die sie Daten empfängt, und Sie diese Daten irgendwo speichern möchten, ist Core Data eine ausgezeichnete Wahl. Welche Probleme könnten Sie damit haben? Das erste und offensichtlichste: Die Datenmenge ist so groß, dass unsere Anwendung beim Versuch, sie zu speichern, für einige Zeit einfriert, was sich auf die Benutzererfahrung auswirkt. Auf eine normale GCD kann nicht verzichtet werden, da sie unabhängig ist. Unser hier erwähnter Core Data Stack funktioniert synchron und für jeden Zugriff auf unseren NSManageObjectContext müssen wir bis zum Ende der Schleife warten.

Aber hier kommt der private NSManageObjectContext, der im Hintergrund-Thread funktioniert, zur Rettung. Um es aufzurufen, müssen Sie sich zuerst an unseren NSPersistentContainer wenden.

Die Initialisierung sieht folgendermaßen aus:

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


Hier geben Sie die Zusammenführungsrichtlinie unseres NSManageObjectContext an. Hier geben wir explizit an, wie sich Core Data im Falle eines Datenkonflikts verhalten soll.

MergePolicy-Optionen:

  1. NSRollbackMergePolicy - Im Falle eines Konflikts werden alle Änderungen verworfen, bis sie auftreten
  2. NSOverwriteMergePolicy - Speichert neue Werte unabhängig von Daten
  3. NSMergeByPropertyStoreTrumpMergePolicy - Speichert geänderte Objekte Eigenschaft für Eigenschaft. In diesem Fall haben gespeicherte Daten Vorrang
  4. NSMergeByPropertyObjectTrumpMergePolicy - Speichert geänderte Objekte Eigenschaft für Eigenschaft. In diesem Fall haben neue Daten Vorrang

AutomaticallyMergesChangesFromParent - Gibt an, ob unser Kontext Daten automatisch zusammenführt.
Erstellen Sie dann einen neuen Kontext:

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

Jetzt haben wir zwei NSManageObjectContext. Der erste dient zum Arbeiten mit der Benutzeroberfläche und wird auf dem Hauptthread ausgeführt, und der zweite verfügt über privateQueueConcurrencyType zum Arbeiten im Hintergrund.

Wir werden es verwenden, um Daten herunterzuladen.

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

Hier erstellen wir unsere Entität und können ihr dann die erforderlichen Eigenschaften zuweisen. Danach rufen wir die Speichermethode auf. Sie sieht folgendermaßen aus:

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

Es stehen 2 Methoden zur Auswahl:

  • performAndWait - führt Aktionen für den Kontext-Thread synchron aus
  • perform - Führt asynchron Aktionen für den Kontextstrom aus


NSFetchedResultsController


NSFetchedResultsController - Ein Controller, der bestimmte Anforderungen ausführt und dem Benutzer die erforderlichen Daten anzeigt.

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 hat eine sehr große Anzahl von Konfigurationen, wir werden einige davon analysieren:

Fetchlimit
FetchLimit —

Sketchoffset
FetchOffset — . 2, .

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

FetchbatchSize
FetchBatchSize — .

SortDescriptor
SortDescriptor — , .

ReturnsObjectsAsFaults
ReturnsObjectsAsFaults — , , , PersistentStore RawCache

Im Moment haben wir einen NSFetchedResultsController, der unsere Daten in einer Tabelle anzeigen soll. Um die Daten zu aktualisieren, müssen Sie die Delegate-Methode aufrufen:

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

Diese Delegate-Methode funktioniert, wenn sich in unserem Kontext Änderungen ergeben. In dieser Implementierung geschieht dies, nachdem wir die Daten in einem privaten Kontext gespeichert haben. In diesem Moment wird die Delegatmethode ausgelöst und die Daten werden aktualisiert.

Nur ein paar Aktionen und Kerndaten aus einer regulären Datenbank werden zu einer mächtigen Waffe eines jeden iOS-Entwicklers.

Viel Spaß beim Codieren!

All Articles