問題:
Todayビューのウィジェット拡張内からアプリケーションのコアデータデータベースにアクセスできません。
アプリ自体は、iOS 8で通常どおりにデータベースの読み取りと書き込みを行うことができますが、拡張機能はストアの作成に失敗し、ファイルに書き込むことができないというエラーが発生します。
ログは次のとおりです。
Error Domain=NSCocoaErrorDomain Code=512 "The operation couldn’t be completed. (Cocoa error 512.)"
reason = "Failed to create file; code = 2
ウィジェットはNSDocumentsディレクトリにアクセスできません。NSDocumentsディレクトリは通常、データベースを保存する場所です。
解決策は、最初にアプリグループを作成することです
移動先:プロジェクト-ターゲット-アプリグループ-新しいコンテナーの追加
コンテナーに名前を付けます(例: 'group.mycontainer')
コンテナに同じ名前を使用して、ウィジェットのターゲットに対してプロセスを繰り返します。
次に、データベースをグループコンテナに書き込みます。
そう:
NSURL *storeURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSAllDomainsMask] lastObject];
storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];
になる:
NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.mycontainer"];
storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];
ストアの初期化は次のようになります。
NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.mycontainer"];
storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];
NSPersistentStore *store = nil;
store = [coordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:nil
error:&error]
標準のiOSバックアップ手順を使用して、アプリグループファイルがバックアップされないことがわかりました。
永続ストアをアプリグループコンテナーに保持すると、iOSの復元後にユーザーがアプリデータをすべて失う可能性があることに注意してください。
[〜#〜] update [〜#〜]
rdar:// 18750178
[〜#〜] update [〜#〜]
iOS 8.1で修正されたようです。Appleみんなからメッセージが送られ、修正されたかどうかiOS 8.1で問題をチェックするように頼まれました(かなり厚かましいですか?)。私はテストしていません。とにかく、欠陥のあるiOS 8.0をサポートしている場合には、AppGroupsにストレージを保持することは考えられません。
変化する
[MagicalRecord setupCoreDataStackWithStoreNamed:@"Database"];
に
- (void)setupCoreDataStack
{
if ([NSPersistentStoreCoordinator MR_defaultStoreCoordinator] != nil)
{
return;
}
NSManagedObjectModel *model = [NSManagedObjectModel MR_defaultManagedObjectModel];
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.yourgroup"];
storeURL = [storeURL URLByAppendingPathComponent:@"Database.sqlite"];
[psc MR_addSqliteStoreNamed:storeURL withOptions:nil];
[NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:psc];
[NSManagedObjectContext MR_initializeDefaultContextWithCoordinator:psc];
}
Swiftでも同じです:
private func setupCoreDataStack() {
if NSPersistentStoreCoordinator.MR_defaultStoreCoordinator() != nil {
return
}
let managedObjectModel = NSManagedObjectModel.MR_defaultManagedObjectModel()
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)
var storePath = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier(PBOSharedSuiteGroupName)
storePath = storePath!.URLByAppendingPathComponent("AppName.sqlite")
var error: NSError?
persistentStoreCoordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storePath, options: nil, error: &error)
NSPersistentStoreCoordinator.MR_setDefaultStoreCoordinator(persistentStoreCoordinator)
NSManagedObjectContext.MR_initializeDefaultContextWithCoordinator(persistentStoreCoordinator)
}
このメソッドをAppDelegateとToday Extensionの両方に添付することを忘れないでください