在iOS 8扩展中访问核心数据SQL数据库(在App和Widget扩展之间共享数据)

Mar*_*ges 34 sqlite iphone core-data ios ios-app-extension

问题:

无法从Today View中的Widget扩展中访问应用程序的Core Data数据库.

应用程序本身能够按照iOS 8中的正常情况读取和写入数据库,但扩展将无法创建存储,导致错误,无法写入文件.

日志如下:

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

reason = "Failed to create file; code = 2
Run Code Online (Sandbox Code Playgroud)

Mar*_*ges 69

窗口小部件无法访问NSDocuments目录,这是人们通常存储其数据库的位置.

解决方案是首先创建一个应用程序组

转至:项目 - 目标 - 应用程序组 - 添加新容器

命名容器,即'group.mycontainer'

使用容器的相同名称重复Widget的Target的过程.

然后将数据库写入组容器.

所以:

NSURL *storeURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory  inDomains:NSAllDomainsMask] lastObject];
storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];
Run Code Online (Sandbox Code Playgroud)

变为:

NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.mycontainer"];
storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];
Run Code Online (Sandbox Code Playgroud)

初始化商店应该是这样的:

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]
Run Code Online (Sandbox Code Playgroud)

  • @Mark数据迁移方案如何工作?想象一下,应用程序将数据存储在原始storeURL中,现在新版本必须首先在新storeURL中创建新文件,然后以某种方式将原始数据迁移到新存储中. (7认同)
  • 但是我如何获得协调员?我需要这个型号(妈妈)吗?如果是,我如何与扩展共享模型? (2认同)

kas*_*kad 7

刚刚发现应用程序组文件没有使用标准的iOS备份程序进行备份.

请记住,如果将持久性存储保留在应用程序组容器中,则用户可能会在还原iOS后丢失所有应用程序数据.

UPDATE

rdar:// 18750178

UPDATE

似乎在iOS 8.1中已修复,苹果公司的人给我发消息并要求检查iOS 8.1中的问题是否已修复(非常不礼貌不是?).我没有测试过,所以请记住.无论如何,如果你支持有缺陷的iOS 8.0,保持AppGroups中的存储是一个死的想法


Igo*_*gor 5

更改

[MagicalRecord setupCoreDataStackWithStoreNamed:@"Database"];
Run Code Online (Sandbox Code Playgroud)

 - (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];
}
Run Code Online (Sandbox Code Playgroud)