core-data
Pila de datos del núcleo
Buscar..
Observaciones
Esta es una implementación de la pila de datos principales que se coloca inicialmente en el archivo AppDelegate
si el proyecto se crea con los datos principales cuando se crea el proyecto. Estas funciones también pueden implementarse en clases separadas para CoreDataStack.swift
. Una de las funciones principales es obtener NSManagedObjectContext.
C objetivo
- (NSManagedObjectContext *)managedObjectContext {...}
Swift 2
lazy var managedObjectContext: NSManagedObjectContext = {...}
Swift 3
lazy var persistentContainer: NSPersistentContainer = {...)
let managedObjectContext = persistentContainer.viewContext
La pila de datos principales que se comunica entre los objetos en su aplicación y los almacenes de datos externos. La pila Core Data maneja todas las interacciones con los almacenes de datos externos para que su aplicación pueda centrarse en su lógica de negocios. La pila consta de tres objetos primarios: el contexto del objeto administrado ( NSManagedObjectContext
), el coordinador de tienda persistente ( NSPersistentStoreCoordinator
) y el modelo de objeto administrado ( NSManagedObjectModel
).
NSManagedObjectModel
La instancia de NSManagedObjectModel
describe los datos a los que la pila Core Data accederá. NSManagedObjectModel
(a menudo denominado "mamá") se carga en la memoria como el primer paso en la creación de la pila. Un ejemplo de NSManagedObjectModel
es DataModel.momd. El NSManagedObjectModel
define la estructura de los datos
NSPersistentStoreCoordinator
El NSPersistentStoreCoordinator
realiza los objetos de los datos en el almacén persistente y pasa esos objetos al NSManagedObjectContext
solicitante. Crea nuevas instancias de las entidades en el modelo y recupera instancias existentes de un almacén persistente ( NSPersistentStore
). El NSPersistentStoreCoordinator
también verifica que los datos se encuentren en un estado coherente que coincida con las definiciones en NSManagedObjectModel
.
NSManagedObjectContext
Cuando recuperas objetos de un almacén persistente, traes copias temporales al bloc de notas donde forman un gráfico de objetos (o una colección de gráficos de objetos). Luego puede modificar esos objetos, a menos que realmente guarde esos cambios, sin embargo, el almacén persistente permanece inalterado.
Todos los objetos gestionados deben registrarse con un contexto de objeto gestionado. Utiliza el contexto para agregar objetos al gráfico de objetos y eliminar objetos del gráfico de objetos. El contexto rastrea los cambios que realiza, tanto a los atributos de los objetos individuales como a las relaciones entre los objetos. Al realizar un seguimiento de los cambios, el contexto puede proporcionarle ayuda para deshacer y rehacer. También garantiza que si cambia las relaciones entre los objetos, se mantiene la integridad del gráfico de objetos.
Cuando guarda los cambios, el contexto garantiza que sus objetos se encuentren en un estado válido. Los cambios se escriben en el almacén (o almacenes) persistentes, se agregan nuevos registros para los objetos que creó y los registros se eliminan para los objetos que eliminó.
Fuente: Apple Core Data Programming: Inicializando la pila de datos Core
Objective-C Ejemplo
Esta es una configuración simple pero robusta de datos básicos para iOS 10+. Hay exactamente dos formas de acceder a los datos principales:
- viewContext . El
viewContext
solo se puede usar desde el hilo principal, y solo para leer. - EnqueueCoreDataBlock fuerte . Toda la escritura debe hacerse utilizando
enqueueCoreDataBlock
. No hay necesidad de guardar al final, se guardará automáticamente. Todas las escrituras se ponen en cola en una OperationQueue para que nunca haya conflictos de escritura.
Asegúrese de que NUNCA use ningún objeto gestionado del contexto en otro contexto. También descarte todos los objetos que se crean o se recuperan en enqueueCoreDataBlock
ya que el contexto que los respalda se destruirá después de que se ejecute el bloque.
// CoreDataManager.h
@interface CoreDataManager : NSObject
@property (nonatomic, readonly) NSManagedObjectContext * viewContext;
- (void)enqueueCoreDataBlock:(void (^)(NSManagedObjectContext* context))block;
@end
// CoreDataManager.m
@implementation NSManagedObjectContext(SaveIfNeeded)
-(BOOL) saveIfNeeded{
BOOL toReturn = YES;
if ([self hasChanges]) {
NSError *error;
toReturn = [self save:&error];
if (toReturn == NO || error)
{
//Here you should log to your analytics service
NSLog(@"--- Failed to commit data\n error: %@", error);
}
}
return toReturn;
}
@end
@interface CoreDataManager ()
@property (nonatomic, strong) NSPersistentContainer* persistentContainer;
@property (nonatomic, strong) NSOperationQueue* persistentContainerQueue;
@end
@implementation CoreDataManager
- (id)init
{
self = [super init]
if (self)
{
self.persistentContainer = [[NSPersistentContainer alloc] initWithName:@"PROJECT_NAME_ALSO_NAME_OF_MODEL" managedObjectModel:managedObjectModel];
[self.persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription * description, NSError * error) {
}];
self.persistentContainer.viewContext.automaticallyMergesChangesFromParent = YES;
_persistentContainerQueue = [[NSOperationQueue alloc] init];
_persistentContainerQueue.maxConcurrentOperationCount = 1;
_persistentContainerQueue.name = @"persistentContainerQueue";
dispatch_queue_t queue = dispatch_queue_create("persistentContainerQueue.dispatchQueue", DISPATCH_QUEUE_SERIAL);
_persistentContainerQueue.underlyingQueue = queue;
}
}
- (void)enqueueCoreDataBlock:(void (^)(NSManagedObjectContext* context))block{
void (^blockCopy)(NSManagedObjectContext*) = [block copy];
[self.persistentContainerQueue addOperation:[NSBlockOperation blockOperationWithBlock:^{
NSManagedObjectContext* context = self.persistentContainer.newBackgroundContext;
[context performBlockAndWait:^{
blockCopy(context);
[context saveIfNeeded];
}];
}]];
}
-(NSManagedObjectContext*) viewContext{
if (![NSThread mainThread]) {
//here you should log to you analytics service. If you are in developer mode you should crash to force you to fix this
NSLog(@"access context on wrong thread!!");
}
return self.persistentContainer.viewContext;
}
Swift 2 Ejemplo
// Core Data stack
lazy var applicationDocumentsDirectory: NSURL = {
let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
return urls[urls.count-1]
}()
lazy var managedObjectModel: NSManagedObjectModel = {
let modelURL = NSBundle.mainBundle().URLForResource("ProjectName", withExtension: "momd")!
return NSManagedObjectModel(contentsOfURL: modelURL)!
}()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
var failureReason = "There was an error creating or loading the application's saved data."
do {
try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil)
} catch {
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReason
dict[NSUnderlyingErrorKey] = error as NSError
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
print("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
abort()
}
return coordinator
}()
lazy var managedObjectContext: NSManagedObjectContext = {
let coordinator = self.persistentStoreCoordinator
var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
// Core Data Saving support
func saveContext () {
if managedObjectContext.hasChanges {
do {
try managedObjectContext.save()
} catch {
let nserror = error as NSError
print("Unresolved error \(nserror), \(nserror.userInfo)")
abort()
}
}
}
Ejemplo de iOS 10 en Swift
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "ProjectName")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
func saveContext () {
let context = persistentContainer.viewContext
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
if context.hasChanges {
print("changes occured")
}else {
print("no changes occured")
}
}