core-data
コアデータスタック
サーチ…
備考
これは、プロジェクトが作成されたときにコアデータを使用してプロジェクトが作成された場合、最初にAppDelegate
ファイルに配置されるコアデータスタックの実装です。これらの関数はCoreDataStack.swift
別のクラスで実装することもできます。主な機能の1つは、NSManagedObjectContextを取得することです。
目標-C
- (NSManagedObjectContext *)managedObjectContext {...}
スウィフト2
lazy var managedObjectContext: NSManagedObjectContext = {...}
スウィフト3
lazy var persistentContainer: NSPersistentContainer = {...)
let managedObjectContext = persistentContainer.viewContext
アプリケーション内のオブジェクトと外部データストア間で通信するコアデータスタック。コアデータスタックは、アプリケーションがビジネスロジックに集中できるように、外部データストアとのすべての対話を処理します。スタックは、管理対象オブジェクトコンテキスト( NSManagedObjectContext
)、永続ストアコーディネータ( NSPersistentStoreCoordinator
)、および管理対象オブジェクトモデル( NSManagedObjectModel
)の3つの主要オブジェクトから構成されます。
NSManagedObjectModel
NSManagedObjectModel
インスタンスは、コアデータスタックによってアクセスされるデータを記述します。 NSManagedObjectModel
(しばしば「ママ」と呼ばれる)は、スタックの作成の最初のステップとしてメモリにロードされます。 NSManagedObjectModel
の例は、DataModel.momdです。 NSManagedObjectModel
は、データの構造を定義します
NSPersistentStoreCoordinator
NSPersistentStoreCoordinator
は、永続ストア内のデータからオブジェクトを認識し、そのオブジェクトを要求元のNSManagedObjectContext
ます。モデル内のエンティティの新しいインスタンスを作成し、既存のインスタンスを永続ストア( NSPersistentStore
)から取得します。 NSPersistentStoreCoordinator
は、データがNSManagedObjectModel
定義と一致する一貫した状態にあることも確認します。
NSManagedObjectContext
永続ストアからオブジェクトをフェッチするときは、テンポラリ・コピーをスクラッチ・パッドに持ってきて、オブジェクト・グラフ(またはオブジェクト・グラフの集合)を形成します。実際に変更を保存しないかぎり、これらのオブジェクトを変更できますが、永続ストアは変更されません。
すべての管理対象オブジェクトは、管理対象オブジェクトコンテキストに登録する必要があります。コンテキストを使用してオブジェクトグラフにオブジェクトを追加し、オブジェクトグラフからオブジェクトを削除します。コンテキストは、個々のオブジェクトの属性とオブジェクト間の関係の両方に加えた変更を追跡します。変更を追跡することによって、コンテキストは元に戻すとやり直しのサポートを提供することができます。また、オブジェクト間の関係を変更すると、オブジェクトグラフの整合性が維持されます。
変更を保存すると、コンテキストによってオブジェクトが有効な状態になります。変更は永続ストア(またはストア)に書き込まれ、作成したオブジェクトの新しいレコードが追加され、削除したオブジェクトのレコードは削除されます。
目的-Cの例
これは、iOS 10以降のシンプルで堅牢なコアデータ設定です。コアデータにアクセスするには、2通りの方法があります。
- viewContext 。
viewContext
は、メインスレッドからのviewContext
専用に使用できます。 - 強いenqueueCoreDataBlock 。すべての書き込みは、
enqueueCoreDataBlock
を使用して行う必要があります。最後に保存する必要はありませんが、自動的に保存されます。すべての書き込みはoperationQueueにエンキューされ、書き込み競合が発生することはありません。
別のコンテキストのコンテキストからmanagedObjectsを絶対に使用しないでください。 enqueueCoreDataBlock
作成またはフェッチされたすべてのオブジェクトも破棄します。ブロックされたコンテキストは、ブロックの実行後に破棄されます。
// 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;
}
スウィフト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()
}
}
}
SwiftのiOS 10の例
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")
}
}