¡Comenzando con Core Data! Difícil en palabras simples [Parte 2]

En este artículo, me gustaría revelar aún más las capacidades de Core Data. Este artículo es una continuación . Realmente espero poder tener la idea de que Core Data no es una de las muchas bases de datos relacionales, sino una herramienta muy poderosa que puede convertirse en un arma integral en el arsenal de cualquier desarrollador de iOS que se precie.

Bueno, empecemos!

Hoy consideramos trabajar con dos NSManageObjectContext y NSFetchedResultsController.

Dos NSManageObjectContext y ¿por qué es necesario?


Si su aplicación usa activamente cualquier API a través de la cual recibe datos, y desea guardar estos datos en algún lugar, entonces Core Data es una excelente opción. ¿Qué problemas podrías tener con esto? La primera y más obvia: la cantidad de datos será tan grande que cuando intente guardarlos, nuestra aplicación se congelará por un tiempo, lo que afectará la experiencia del usuario. No se puede prescindir de un GCD ordinario aquí, ya que independientemente, nuestra Pila de datos principales, que se mencionó aquí , funciona de forma sincronizada y para cualquier acceso a nuestro NSManageObjectContext tenemos que esperar hasta el final del ciclo.

Pero aquí el NSManageObjectContext privado que funciona en el hilo de fondo viene al rescate. Para llamarlo, primero debe comunicarse con nuestro NSPersistentContainer.

La inicialización se verá así:

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


Aquí especifica la política de fusión de nuestro NSManageObjectContext. Aquí indicamos explícitamente cómo deben comportarse los datos centrales en caso de conflicto de datos.

Opciones de MergePolicy:

  1. NSRollbackMergePolicy: en caso de conflicto, descarta todos los cambios hasta que ocurra
  2. NSOverwriteMergePolicy: guarda nuevos valores independientemente de los datos
  3. NSMergeByPropertyStoreTrumpMergePolicy: guarda los objetos modificados propiedad por propiedad, en este caso, prevalecerán los datos guardados
  4. NSMergeByPropertyObjectTrumpMergePolicy: guarda los objetos modificados propiedad por propiedad, en este caso prevalecerán los datos nuevos

AutomaticallyMergesChangesFromParent : indica si nuestro contexto fusionará automáticamente los datos.
Luego, cree un nuevo contexto:

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

Ahora tenemos dos NSManageObjectContext. El primero es para trabajar con la interfaz de usuario y se ejecuta en el hilo principal, y el segundo tiene privateQueueConcurrencyType para trabajar en segundo plano.

Lo usaremos para descargar datos.

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

Aquí creamos nuestra Entidad y luego podemos asignarle las propiedades necesarias, después de lo cual llamamos el método de guardar, se ve así:

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

Hay 2 métodos para elegir:

  • performAndWait: realiza acciones en el hilo de contexto sincrónicamente
  • realizar: realiza acciones en la secuencia de contexto de forma asincrónica


NSFetchedResultsController


NSFetchedResultsController: un controlador que realiza ciertas solicitudes y muestra los datos necesarios al usuario.

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 tiene una gran cantidad de configuraciones, analizaremos algunas de ellas:

Fetchlimit
FetchLimit —

Sketchoffset
FetchOffset — . 2, .

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

FetchbatchSize
FetchBatchSize — .

SortDescriptor
SortDescriptor — , .

ReturnsObjectsAsFaults
ReturnsObjectsAsFaults — , , , PersistentStore RawCache

Por el momento, tenemos un NSFetchedResultsController que debe mostrar nuestros datos en una tabla. Para actualizar los datos, debe llamar al método delegado:

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

Este método de delegado funciona cuando tenemos algún cambio en nuestro contexto. En esta implementación, esto sucede después de guardar los datos en un contexto privado. En este momento, se activa el método delegado y se actualizan los datos.

Solo un par de acciones y Core Data de una base de datos normal se convierten en un arma poderosa de cualquier desarrollador de iOS.

¡Feliz codificación!

All Articles