Recherche…


Remarques

Il s'agit d'une implémentation de la pile de données principale qui est initialement placée dans le fichier AppDelegate si le projet est créé avec les données de base lors de la création du projet. Ces fonctions peuvent également être implémentées dans une classe distincte pour CoreDataStack.swift . L'une des principales fonctions consiste à obtenir le NSManagedObjectContext.

Objectif c

- (NSManagedObjectContext *)managedObjectContext {...}

Swift 2

lazy var managedObjectContext: NSManagedObjectContext = {...}

Swift 3

lazy var persistentContainer: NSPersistentContainer = {...)
let managedObjectContext = persistentContainer.viewContext

La pile de données de base qui communique entre les objets de votre application et les magasins de données externes. La pile Core Data gère toutes les interactions avec les magasins de données externes afin que votre application puisse se concentrer sur sa logique métier. La pile se compose de trois objets principaux: le contexte d'objet géré ( NSManagedObjectContext ), le coordinateur de magasin persistant ( NSPersistentStoreCoordinator ) et le modèle d'objet géré ( NSManagedObjectModel ).

NSManagedObjectModel

L'instance NSManagedObjectModel décrit les données auxquelles la pile de données Core doit accéder. NSManagedObjectModel (souvent appelé «maman») est chargé en mémoire comme première étape de la création de la pile. Un exemple de NSManagedObjectModel est DataModel.momd. NSManagedObjectModel définit la structure des données

NSPersistentStoreCoordinator

NSPersistentStoreCoordinator réalise des objets à partir des données du magasin persistant et transmet ces objets au NSManagedObjectContext demandeur. Il crée de nouvelles instances des entités dans le modèle et récupère les instances existantes dans un magasin persistant ( NSPersistentStore ). NSPersistentStoreCoordinator vérifie également que les données sont dans un état cohérent qui correspond aux définitions de NSManagedObjectModel .

NSManagedObjectContext

Lorsque vous récupérez des objets à partir d'un magasin persistant, vous apportez des copies temporaires sur le bloc-notes où ils forment un graphique d'objet (ou une collection de graphiques d'objet). Vous pouvez ensuite modifier ces objets, sauf si vous enregistrez réellement ces modifications, cependant, le stockage persistant reste inchangé.

Tous les objets gérés doivent être enregistrés avec un contexte d'objet géré. Vous utilisez le contexte pour ajouter des objets au graphique d'objet et supprimer des objets du graphique d'objet. Le contexte suit les modifications apportées aux attributs des objets individuels et aux relations entre les objets. En effectuant le suivi des modifications, le contexte peut vous aider à annuler et à rétablir. Cela garantit également que si vous modifiez les relations entre les objets, l'intégrité du graphe d'objet est conservée.

Lorsque vous enregistrez des modifications, le contexte garantit que vos objets sont dans un état valide. Les modifications sont écrites dans le ou les magasins persistants, de nouveaux enregistrements sont ajoutés pour les objets que vous avez créés et les enregistrements sont supprimés pour les objets que vous avez supprimés.

Source: Programmation de données Apple Core: initialisation de la pile de données principale

Exemple d'objectif-C

Il s'agit d'une configuration de données de base simple mais robuste pour iOS 10+. Il y a exactement deux façons d'accéder aux données de base:

  1. viewContext . Le viewContext ne peut être utilisé qu'à partir du thread principal et uniquement pour la lecture.
  2. forte enqueueCoreDataBlock . Toute écriture doit être effectuée à l'aide de enqueueCoreDataBlock . Il n'est pas nécessaire de sauvegarder à la fin, il sera automatiquement enregistré. Toutes les écritures sont mises en file d'attente dans operationQueue pour qu'il n'y ait jamais de conflits d'écriture.

Assurez-vous de ne JAMAIS utiliser des ObjectObjects du contexte dans un autre contexte. enqueueCoreDataBlock également tous les objets créés ou extraits dans enqueueCoreDataBlock car le contexte qui les sauvegarde sera détruit après l'exécution du bloc.

// 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 Exemple

// 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()
        }
    }
}

Exemple iOS 10 dans 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")
    }
    
}


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow