web-dev-qa-db-ja.com

iOS 8拡張機能のコアデータSQLデータベースへのアクセス(アプリとウィジェットの拡張機能間でのデータの共有)

問題:

Todayビューのウィジェット拡張内からアプリケーションのコアデータデータベースにアクセスできません。

アプリ自体は、iOS 8で通常どおりにデータベースの読み取りと書き込みを行うことができますが、拡張機能はストアの作成に失敗し、ファイルに書き込むことができないというエラーが発生します。

ログは次のとおりです。

Error Domain=NSCocoaErrorDomain Code=512 "The operation couldn’t be completed. (Cocoa error 512.)"

reason = "Failed to create file; code = 2
34
Mark Bridges

ウィジェットは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]
69
Mark Bridges

標準のiOSバックアップ手順を使用して、アプリグループファイルがバックアップされないことがわかりました。

永続ストアをアプリグループコンテナーに保持すると、iOSの復元後にユーザーがアプリデータをすべて失う可能性があることに注意してください。

[〜#〜] update [〜#〜]

rdar:// 18750178

[〜#〜] update [〜#〜]

iOS 8.1で修正されたようです。Appleみんなからメッセージが送られ、修正されたかどうかiOS 8.1で問題をチェックするように頼まれました(かなり厚かましいですか?)。私はテストしていません。とにかく、欠陥のあるiOS 8.0をサポートしている場合には、AppGroupsにストレージを保持することは考えられません。

7
kas-kad

変化する

[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];
}
5
Igor

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)
}

このメソッドをAppDelegateToday Extensionの両方に添付することを忘れないでください