Szukaj…


Uwagi

Jest to implementacja stosu danych podstawowych, który jest początkowo umieszczany w pliku AppDelegate , jeśli projekt jest tworzony przy użyciu danych podstawowych podczas tworzenia projektu. Funkcje te można również zaimplementować w osobnej klasie dla CoreDataStack.swift . Jedną z głównych funkcji jest uzyskanie NSManagedObjectContext.

Cel C

- (NSManagedObjectContext *)managedObjectContext {...}

Swift 2

lazy var managedObjectContext: NSManagedObjectContext = {...}

Szybki 3

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

Stos danych podstawowych, który komunikuje się między obiektami w aplikacji a zewnętrznymi magazynami danych. Stos danych podstawowych obsługuje wszystkie interakcje z zewnętrznymi magazynami danych, dzięki czemu aplikacja może skupić się na logice biznesowej. Stos składa się z trzech podstawowych obiektów: kontekstu obiektu zarządzanego ( NSManagedObjectContext ), koordynatora przechowywania trwałego ( NSPersistentStoreCoordinator ) i modelu obiektu zarządzanego ( NSManagedObjectModel ).

NSManagedObjectModel

Instancja NSManagedObjectModel opisuje dane, które będą dostępne przez stos danych podstawowych. NSManagedObjectModel (często nazywany „mamą”) jest ładowany do pamięci jako pierwszy krok w tworzeniu stosu. Przykładem NSManagedObjectModel jest DataModel.momd. NSManagedObjectModel określa strukturę danych

NSPersistentStoreCoordinator

NSPersistentStoreCoordinator realizuje obiekty z danych w trwałym magazynie i przekazuje te obiekty do żądającego NSManagedObjectContext . Tworzy nowe wystąpienia encji w modelu i pobiera istniejące wystąpienia z trwałego magazynu ( NSPersistentStore ). NSPersistentStoreCoordinator sprawdza również, czy dane są w spójnym stanie zgodnym z definicjami w NSManagedObjectModel .

NSManagedObjectContext

Podczas pobierania obiektów z trwałego magazynu, przenosisz tymczasowe kopie na notatnik, gdzie tworzą wykres obiektów (lub zbiór wykresów obiektów). Następnie możesz zmodyfikować te obiekty, chyba że faktycznie zapiszesz te zmiany, jednak trwały magazyn pozostaje niezmieniony.

Wszystkie zarządzane obiekty muszą być zarejestrowane w kontekście zarządzanych obiektów. Kontekst służy do dodawania obiektów do wykresu obiektów i usuwania obiektów z wykresu obiektów. Kontekst śledzi wprowadzane zmiany, zarówno w odniesieniu do atrybutów poszczególnych obiektów, jak i relacji między obiektami. Śledząc zmiany, kontekst może zapewnić obsługę cofania i ponawiania. Zapewnia również, że jeśli zmienisz relacje między obiektami, zachowana zostanie integralność grafu obiektowego.

Podczas zapisywania zmian kontekst zapewnia, że Twoje obiekty są w poprawnym stanie. Zmiany są zapisywane w trwałym magazynie (lub sklepach), nowe rekordy są dodawane do obiektów, które utworzyłeś, a rekordy są usuwane dla obiektów, które usunąłeś.

Źródło: Programowanie podstawowych danych Apple: Inicjowanie stosu danych podstawowych

Przykład celu C

Jest to prosta, ale solidna konfiguracja podstawowych danych dla systemu iOS 10+. Istnieją dokładnie dwa sposoby dostępu do danych podstawowych:

  1. viewContext . viewContext może być używany tylko z głównego wątku i tylko do odczytu.
  2. strong enqueueCoreDataBlock . Całe pisanie powinno odbywać się za pomocą enqueueCoreDataBlock . Nie ma potrzeby zapisywania na końcu - zapisuje się automatycznie. Wszystkie zapisy są kolejkowane w kolejce operacji, więc nigdy nie będzie konfliktów zapisu.

Pamiętaj, aby NIGDY nie używać żadnych obiektów zarządzanych z kontekstu w innym kontekście. Odrzuć również wszystkie obiekty, które są tworzone lub pobierane w enqueueCoreDataBlock ponieważ kontekst, który je popiera, zostanie zniszczony po wykonaniu bloku.

// 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;
}

Przykład Swift 2

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

Przykład iOS 10 w 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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow