core-data
Core Data Stack
Suche…
Bemerkungen
Dies ist eine Implementierung des Core Data Stack, die anfänglich in der AppDelegate
Datei AppDelegate
wird, wenn das Projekt beim AppDelegate
des Projekts mit Core Data erstellt wird. Diese Funktionen können auch in einer separaten Klasse für CoreDataStack.swift
. Eine der wichtigsten Funktionen ist das Abrufen des NSManagedObjectContext.
Ziel c
- (NSManagedObjectContext *)managedObjectContext {...}
Schnell 2
lazy var managedObjectContext: NSManagedObjectContext = {...}
Swift 3
lazy var persistentContainer: NSPersistentContainer = {...)
let managedObjectContext = persistentContainer.viewContext
Der Core Data Stack, der zwischen den Objekten in Ihrer Anwendung und externen Datenspeichern kommuniziert. Der Core-Data-Stack übernimmt alle Interaktionen mit den externen Datenspeichern, sodass sich Ihre Anwendung auf ihre Geschäftslogik konzentrieren kann. Der Stapel besteht aus drei primären Objekten: dem Kontext für verwaltete Objekte ( NSManagedObjectContext
), dem Koordinator für persistenten Speicher ( NSPersistentStoreCoordinator
) und dem Modell für verwaltete Objekte ( NSManagedObjectModel
).
NSManagedObjectModel
Die NSManagedObjectModel
Instanz beschreibt die Daten, auf die der Core Data-Stack NSManagedObjectModel
soll. NSManagedObjectModel
(oft als "Mom" bezeichnet) wird als erster Schritt bei der Erstellung des Stacks in den Speicher geladen. Ein Beispiel für das NSManagedObjectModel
ist DataModel.momd. Das NSManagedObjectModel
definiert die Struktur der Daten
NSPersistentStoreCoordinator
Der NSPersistentStoreCoordinator
realisiert Objekte aus den Daten im permanenten Speicher und übergibt diese an den anfordernden NSManagedObjectContext
. Es erstellt neue Instanzen der Entitäten im Modell und ruft vorhandene Instanzen aus einem permanenten Speicher ab ( NSPersistentStore
). Der NSPersistentStoreCoordinator
überprüft auch, ob sich die Daten in einem konsistenten Zustand befinden, der den Definitionen im NSManagedObjectModel
.
NSManagedObjectContext
Wenn Sie Objekte aus einem permanenten Speicher abrufen, bringen Sie temporäre Kopien auf den Notizblock, wo sie ein Objektdiagramm (oder eine Sammlung von Objektdiagrammen) bilden. Sie können diese Objekte dann ändern, sofern Sie diese Änderungen nicht wirklich speichern. Der persistente Speicher bleibt jedoch unverändert.
Alle verwalteten Objekte müssen mit einem verwalteten Objektkontext registriert werden. Sie verwenden den Kontext, um Objekte zum Objektdiagramm hinzuzufügen und Objekte aus dem Objektdiagramm zu entfernen. Der Kontext verfolgt die Änderungen, die Sie vornehmen, sowohl an den Attributen einzelner Objekte als auch an den Beziehungen zwischen Objekten. Durch das Nachverfolgen von Änderungen kann der Kontext Sie rückgängig machen und wiederholen. Dadurch wird auch sichergestellt, dass beim Ändern von Beziehungen zwischen Objekten die Integrität des Objektdiagramms erhalten bleibt.
Wenn Sie Änderungen speichern, stellt der Kontext sicher, dass sich Ihre Objekte in einem gültigen Status befinden. Die Änderungen werden in den permanenten Speicher (oder in die Speicher) geschrieben, neue Datensätze werden für von Ihnen erstellte Objekte hinzugefügt und Datensätze für gelöschte Objekte werden entfernt.
Quelle: Apple Core Data Programming: Initialisieren des Core Data Stack
Ziel-C-Beispiel
Dies ist ein einfaches, aber robustes Core-Data-Setup für iOS 10+. Es gibt genau zwei Möglichkeiten, auf Kerndaten zuzugreifen:
- viewContext . Der
viewContext
kann nur vom Haupt-Thread und nur zum Lesen verwendet werden. - starker enqueueCoreDataBlock . Alles Schreiben sollte mit
enqueueCoreDataBlock
. Es ist nicht notwendig, am Ende zu speichern, es wird automatisch gespeichert. Alle Schreibvorgänge werden in einer operationQueue in eine Warteschlange gestellt, sodass es nie zu Schreibkonflikten kommen kann.
Stellen Sie sicher, dass Sie NIEMALS verwalteteObjekte aus dem Kontext in einem anderen Kontext verwenden. enqueueCoreDataBlock
auch alle Objekte, die in enqueueCoreDataBlock
als Kontext erstellt oder abgerufen werden, der sie unterstützt, nachdem der Block ausgeführt wird.
// 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 Beispiel
// 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()
}
}
}
iOS 10 Beispiel in 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")
}
}