NSPersistentStoreDescription のデフォルト値とカスタマイズ
iOS 10で導入された NSPersistentContainer
を使うとCore Dataのセットアップのコードがずいぶん短くなる。Xcode のテンプレートはこんな感じ
- (NSPersistentContainer *)persistentContainer { @synchronized (self) { if (_persistentContainer == nil) { _persistentContainer = [[NSPersistentContainer alloc] initWithName:@"AppName"]; [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) { if (error != nil) { NSLog(@"Unresolved error %@, %@", error, error.userInfo); abort(); } }]; } } return _persistentContainer; }
これだけで済んでしまう。
でも以前セットアップで使ってた NSMigratePersistentStoresAutomaticallyOption
NSInferMappingModelAutomaticallyOption
NSSQLitePragmasOption
といったオプション設定はどうなっているの?と疑問に思ったので調査。
設定内容は _persistentContainer.persistentStoreDescriptions
で取得できる NSPersistentStoreDescription
のインスタンスから参照出来るらしい。
このインスタンスから取得可能なプロパティを調べてみると以下の様になった。
property | value |
---|---|
type | SQLite |
configuration | null |
URL | ~/Library/Application Support/<Name>.sqlite |
options | { NSInferMappingModelAutomaticallyOption = 1; NSMigratePersistentStoresAutomaticallyOption = 1; } |
readOnly | NO |
timeout | 240 |
sqlitePragmas | { } |
shouldAddStoreAsynchronously | NO |
shouldMigrateStoreAutomatically | YES |
shouldInferMappingModelAutomatically | YES |
設定をカスタマイズする
loadPersistentStoresWithCompletionHandler:
を呼ぶ前に NSPersistentStoreDescription
の各値を設定する事でカスタマイズが出来る。
例えば URL
の様に readwrite なプロパティはそのまま素直に変更可能
_persistentContainer = [[NSPersistentContainer alloc] initWithName:@"AppName"]; NSPersistentStoreDescription *storeDescription = _persistentContainer.persistentStoreDescriptions.firstObject; NSURL *URL = [storeDescription.URL.URLByDeletingLastPathComponent URLByAppendingPathComponent:@"NewLocation.sqlite"]; storeDescription.URL = URL; [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
options
と sqlitePragmas
は readonly なプロパティになっている代わりに以下の値設定用のメソッドが用意されているのでこれを使う。
- (void)setOption:(nullable NSObject *)option forKey:(NSString *)key; - (void)setValue:(nullable NSObject *)value forPragmaNamed:(NSString *)name;
例えば以下で SQLite の journal_mode を shm とwal ファイルを生成しない DELETE モードに設定する事が出来る。
_persistentContainer = [[NSPersistentContainer alloc] initWithName:@"AppName"]; NSPersistentStoreDescription *storeDescription = _persistentContainer.persistentStoreDescriptions.firstObject; [storeDescription setValue:@"DELETE" forPragmaNamed:@"journal_mode"]; [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
これらのメソッドを使えばCore Dataのセットアップが従来通り柔軟に出来そうな目処が立つ。
ちなみに shouldMigrateStoreAutomatically
と shouldInferMappingModelAutomatically
を NO
にすると options
の NSInferMappingModelAutomaticallyOption
と NSMigratePersistentStoresAutomaticallyOption
も NO
になっていた。
おそらくこれらは良く使うオプションなのでプロパティのフラグ設定と自動で連携して簡単に options
にキーと値を設定してくれる様になっているらしい。
参考 SQLite の pragma のリスト
https://sqlite.org/pragma.html