LoginSignup
10
10

More than 5 years have passed since last update.

MagicalRecordの中身探訪(セットアップ、NSManagedObjectContext周辺)

Last updated at Posted at 2013-11-22

コード書いてて色々よくわからなかったのでメモ。


デフォルトのpersistentStoreCoordinator

CoreData初期化時に特に指定がなければSQLiteストアを使用する。

MagicalRecord+Setup.m
+ (void) setupCoreDataStack
{
    [self setupCoreDataStackWithStoreNamed:[self defaultStoreName]];
}

+ (void) setupCoreDataStackWithStoreNamed:(NSString *)storeName
{
    if ([NSPersistentStoreCoordinator MR_defaultStoreCoordinator] != nil) return;

    NSPersistentStoreCoordinator *coordinator = [NSPersistentStoreCoordinator MR_coordinatorWithSqliteStoreNamed:storeName];
    [NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:coordinator];

    [NSManagedObjectContext MR_initializeDefaultContextWithCoordinator:coordinator];
}

デフォルトのSQLiteデータベースファイル名

作成されるファイルはアプリ名(kCFBundleNameKey)+ .sqliteとなる。アプリ名がSampleAppであればSampleApp.sqliteというファイルになる。

MagicalRecord.m
+ (NSString *) defaultStoreName;
{
    NSString *defaultName = [[[NSBundle mainBundle] infoDictionary] valueForKey:(id)kCFBundleNameKey];
    if (defaultName == nil)
    {
        defaultName = kMagicalRecordDefaultStoreFileName;
    }
    if (![defaultName hasSuffix:@"sqlite"]) 
    {
        defaultName = [defaultName stringByAppendingPathExtension:@"sqlite"];
    }

    return defaultName;
}

デフォルトのNSManagementObjectContext

[NSManagedObjectContext MR_defaultContext]で取得できるコンテキストは、アプリケーション起動後に最初にsetupしたpersistentStoreCoordinator(SQLiteストア)を利用したコンテキストが返される。

NSManagedObjectContext+MagicalRecord.m
+ (NSManagedObjectContext *) MR_defaultContext
{
    @synchronized (self)
    {
        NSAssert(defaultManagedObjectContext_ != nil, @"Default Context is nil! Did you forget to initialize the Core Data Stack?");
        return defaultManagedObjectContext_;
    }
}

iCloudストアを利用した場合はNSNotificationCenterのオブザーバ設定が行われる。

NSManagedObjectContext+MagicalRecord.m
+ (void) MR_setDefaultContext:(NSManagedObjectContext *)moc
{
    if (defaultManagedObjectContext_)
    {
        [[NSNotificationCenter defaultCenter] removeObserver:defaultManagedObjectContext_];
    }

    NSPersistentStoreCoordinator *coordinator = [NSPersistentStoreCoordinator MR_defaultStoreCoordinator];
    if (iCloudSetupNotificationObserver)
    {
        [[NSNotificationCenter defaultCenter] removeObserver:iCloudSetupNotificationObserver];
        iCloudSetupNotificationObserver = nil;
    }

    if ([MagicalRecord isICloudEnabled]) 
    {
        [defaultManagedObjectContext_ MR_stopObservingiCloudChangesInCoordinator:coordinator];
    }

    defaultManagedObjectContext_ = moc;
    [defaultManagedObjectContext_ MR_setWorkingName:@"DEFAULT"];

//    [moc MR_obtainPermanentIDsBeforeSaving];
    if ([MagicalRecord isICloudEnabled])
    {
        [defaultManagedObjectContext_ MR_observeiCloudChangesInCoordinator:coordinator];
    }
    else
    {
        // If icloud is NOT enabled at the time of this method being called, listen for it to be setup later, and THEN set up observing cloud changes
        iCloudSetupNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMagicalRecordPSCDidCompleteiCloudSetupNotification
                                                                           object:nil
                                                                            queue:[NSOperationQueue mainQueue]
                                                                       usingBlock:^(NSNotification *note) {
                                                                           [[NSManagedObjectContext MR_defaultContext] MR_observeiCloudChangesInCoordinator:coordinator];
                                                                       }];        
    }
    MRLog(@"Set Default Context: %@", defaultManagedObjectContext_);
}

ローカルなコンテキスト

[NSManagedObjectContext MR_context]を実行すると、parentContextにデフォルトコンテキストが代入されたローカルなNSManagedObjectContextオブジェクトを取得することが出来る。

NSManagedObjectContext+MagicalRecord.m
+ (NSManagedObjectContext *) MR_context;
{
    NSManagedObjectContext *context = [[self alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [context setParentContext:[self MR_defaultContext]];
    return context;
}

スレッドコンテキスト

NSManagedObjectContext MR_contextForCurrentThread]を使用するとスレッドローカルなNSManagedObjectContextを取得することが出来る。上記のローカルなコンテキスト(この呼び方でいいのか?)とは、MR_contextForCurrentThreadを経由して取得すると、メインスレッドかそれ以外かを考慮したスレッドが返却される点が異なる。

メインスレッドから呼び出した場合はdefualtContextが、それ以外は上記と同様ローカルなコンテキストが返る。

NSManagedObjectContext+MagicalThreading.m
+ (NSManagedObjectContext *) MR_contextForCurrentThread;
{
    if ([NSThread isMainThread])
    {
        return [self MR_defaultContext];
    }
    else
    {
        NSMutableDictionary *threadDict = [[NSThread currentThread] threadDictionary];
        NSManagedObjectContext *threadContext = [threadDict objectForKey:kMagicalRecordManagedObjectContextKey];
        if (threadContext == nil)
        {
            threadContext = [self MR_contextWithParent:[NSManagedObjectContext MR_defaultContext]];
            [threadDict setObject:threadContext forKey:kMagicalRecordManagedObjectContextKey];
        }
        return threadContext;
    }
}
10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10