一般規定
要するに、コアデータスタックはいくつかの主要部分で構成されています。
1)NSPersistentStore。バイナリファイル、XML、SQLiteファイルを使用できます。
2)NSManagedObjectModel。これは、データモデルのコンパイル済みバイナリバージョンです。
3)NSPersistentStoreCoordinatorは、NSPersistentStoreおよびNSManagedObjectModelからのデータのロード、保存およびキャッシュに従事しています。
4)NSManagedObjectContext、NSPersistentStoreからメモリへのデータのロード、インスタンスの操作。
5)NSManagedObject-データモデルのオブジェクト。
私の意見では、この奇跡の主な不快な特徴は、NSManagedObjectContextがスレッドセーフではないということです。
スタックの初期化
データベースサイズが大きいと、移行中にメインスレッドのスタックの初期化に30秒以上かかることがあります。 これにより、システムは単にアプリケーションを強制終了します。 解決方法があります。別のスレッドでスタックを初期化します。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // NSManagedObjectModel NSURL *modelURL = [[NSBundle mainBundle] URLForResource:kModelFileName withExtension:@"momd"]; NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; // NSPersistentStoreCoordinator NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom]; // NSPersistentStoreCoordinator , NSURL *doURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; NSURL *storeURL = [doURL URLByAppendingPathComponent:@"CoreData.sqlite"]; NSError *error = nil; NSPersistentStore *store = [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]; // });
そのため、アプリケーションが起動され、ユーザーはUIラグを受け取らず、誰もが満足しています。 さらに続きます。
メインコンテキストの作成
上で書いたように、NSManagedObjectContextはスレッドセーフではありません。 したがって、メインスレッドでメインアプリケーションコンテキストを保持することが適切です。 しかし、この場合、このコンテキストを維持しながらUIが遅くなります。どうすればよいですか? しかし、ここでは、iOS 6でNSManagedObjectContext型が登場しました。
1)NSMainQueueConcurrencyType-メインスレッドからのみ利用可能。
2)NSPrivateQueueConcurrencyType-バックグラウンドスレッドで実行されます。
3)NSConfinementConcurrencyType-作成されたスレッドで実行されます。
また、子コンテキストを作成する機会。 保存するとき、子コンテキストはすべての変更を親にプッシュします。 したがって、次のように、CoreDataを操作するためのマネージャーを装備する機会があります。
// . // _daddyManagedObjectContext , . _daddyManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; [_daddyManagedObjectContext setPersistentStoreCoordinator:psc]; // main-thread context, dispatch_async(dispatch_get_main_queue(), ^{ _defaultManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; // , [_defaultManagedObjectContext setParentContext:_daddyManagedObjectContext]; });
この時点で、コアデータを操作するためのマネージャーの初期化が終了し、メインスレッドの娘だけでなく、pr索好きな目から隠された父親のコンテキストができました。
子コンテキストの作成
簡単に推測できるように、バックグラウンドフローで作業する場合、上記で作成した子コンテキストを祖先として追加するだけで、コンテキストを作成できます。
- (NSManagedObjectContext *)getContextForBGTask { NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; [context setParentContext:_defaultManagedObjectContext]; return context; }
このコンテキストを保存すると、その親への変更が常に保存されます。 したがって、_defaultManagedObjectContext(実際の親に変更をプッシュする)には常に最も関連性の高い情報があります。
コンテキストの保存
残された最も重要なことは保存です。 バックグラウンドストリームに存在するコンテキストは、performBlock:およびperformBlockAndWait:を介してのみアクセスできます。 したがって、バックグラウンドストリームの保存は次のようになります。
- (void)saveContextForBGTask:(NSManagedObjectContext *)bgTaskContext { if (bgTaskContext.hasChanges) { [bgTaskContext performBlockAndWait:^{ NSError *error = nil; [backgroundTaskContext save:&error]; }]; // Save default context } }
子コンテキストを保存したら、親を保存する必要があります。
- (void)saveDefaultContext:(BOOL)wait { if (_defaultManagedObjectContext.hasChanges) { [_defaultManagedObjectContext performBlockAndWait:^{ NSError *error = nil; [_defaultManagedObjectContext save:&error]; }]; } // _defaultManagedObjectContext , _daddyManagedObjectContext void (^saveDaddyContext) (void) = ^{ NSError *error = nil; [_daddyManagedObjectContext save:&error]; }; if ([_daddyManagedObjectContext hasChanges]) { if (wait) [_daddyManagedObjectContext performBlockAndWait:saveDaddyContext]; else [_daddyManagedObjectContext performBlock:saveDaddyContext]; } }
おわりに
数年の間、私は開発者からCore Dataに多くのマイナスがあるとよく耳にします。そのため、たとえばFMDBを優先して選択します。 この記事の目的は、まさにこの神話を払拭することです。
Core Dataを操作するために多くのフレームワークが作成されていますが、メインのフレームワークはMagicalRecordです。 膨大な機能が含まれています。 内部で上記の方法に従ってほぼ動作することは注目に値します。 フレームワークは適切に適用する必要があります。つまり、その仕組みを理解する必要があります。
以上です。 ご清聴ありがとうございました。