core-data
Kerngegevensstapel
Zoeken…
Opmerkingen
Dit is een implementatie van de Core Data Stack die in eerste instantie in het AppDelegate
bestand wordt geplaatst als het project met Core Data wordt gemaakt wanneer het project wordt gemaakt. Deze functies kunnen ook worden geïmplementeerd in een afzonderlijke klasse voor CoreDataStack.swift
. Een van de belangrijkste functies is het ophalen van NSManagedObjectContext.
Doelstelling C
- (NSManagedObjectContext *)managedObjectContext {...}
Swift 2
lazy var managedObjectContext: NSManagedObjectContext = {...}
Swift 3
lazy var persistentContainer: NSPersistentContainer = {...)
let managedObjectContext = persistentContainer.viewContext
De Core Data-stapel die communiceert tussen de objecten in uw applicatie en externe datastores. De Core Data-stack verwerkt alle interacties met de externe datastores zodat uw toepassing zich kan concentreren op de bedrijfslogica. De stapel bestaat uit drie primaire objecten: de beheerde objectcontext ( NSManagedObjectContext
), de persistente winkelcoördinator ( NSPersistentStoreCoordinator
) en het beheerde objectmodel ( NSManagedObjectModel
).
NSManagedObjectModel
De NSManagedObjectModel
instantie beschrijft de gegevens waartoe de Core Data-stapel toegang heeft. NSManagedObjectModel
(vaak de 'moeder' genoemd) wordt in het geheugen geladen als de eerste stap bij het maken van de stapel. Een voorbeeld van het NSManagedObjectModel
is DataModel.momd. Het NSManagedObjectModel
definieert de structuur van de gegevens
NSPersistentStoreCoordinator
De NSPersistentStoreCoordinator
realiseert objecten uit de gegevens in de persistent store en geeft deze objecten door aan de aanvragende NSManagedObjectContext
. Het maakt nieuwe exemplaren van de entiteiten in het model en haalt bestaande exemplaren op uit een persistent store ( NSPersistentStore
). De NSPersistentStoreCoordinator
controleert ook of de gegevens een consistente status hebben die overeenkomt met de definities in het NSManagedObjectModel
.
NSManagedObjectContext
Wanneer u objecten uit een blijvende winkel haalt, brengt u tijdelijke kopieën naar het kladblok waar ze een objectgrafiek vormen (of een verzameling objectgrafieken). U kunt deze objecten vervolgens wijzigen, tenzij u deze wijzigingen daadwerkelijk opslaat, maar de permanente opslag blijft ongewijzigd.
Alle beheerde objecten moeten worden geregistreerd met een beheerde objectcontext. U gebruikt de context om objecten aan de objectgrafiek toe te voegen en objecten uit de objectgrafiek te verwijderen. De context houdt de wijzigingen bij die u aanbrengt, zowel in de kenmerken van afzonderlijke objecten als in de relaties tussen objecten. Door wijzigingen bij te houden, kan de context u ongedaan maken en opnieuw ondersteunen. Het zorgt er ook voor dat als u relaties tussen objecten verandert, de integriteit van de objectgrafiek behouden blijft.
Wanneer u wijzigingen opslaat, zorgt de context ervoor dat uw objecten zich in een geldige status bevinden. De wijzigingen worden naar de permanente winkel (of winkels) geschreven, nieuwe records worden toegevoegd voor objecten die u hebt gemaakt en records zijn verwijderd voor objecten die u hebt verwijderd.
Bron: Apple Core Data Programming: de Core Data Stack initialiseren
Doelstelling-C-voorbeeld
Dit is een eenvoudige maar robuuste set-up van kerngegevens voor iOS 10+. Er zijn precies twee manieren om toegang te krijgen tot kerngegevens:
- viewContext . De
viewContext
kan alleen worden gebruikt vanuit de hoofdthread en alleen voor lezen. - sterke enqueueCoreDataBlock . Al het schrijven moet gebeuren met
enqueueCoreDataBlock
. Het is niet nodig om op te slaan, het wordt automatisch opgeslagen. Alle schrijfbewerkingen worden in de wachtrij geplaatst zodat er nooit schrijfconflicten kunnen zijn.
Zorg ervoor dat u NOOIT managedObjects uit context in een andere context gebruikt. Gooi ook alle objecten weg die zijn gemaakt of opgehaald in enqueueCoreDataBlock
omdat de context die ze ondersteunt wordt vernietigd nadat het blok is uitgevoerd.
// 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-voorbeeld
// 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-voorbeeld 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")
}
}