34

问题:

无法从今日视图中的小部件扩展中访问应用程序的核心数据数据库。

应用本身在iOS 8下可以正常读写数据库,但是扩展无法创建存储,报错,无法写入文件。

日志如下:

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

reason = "Failed to create file; code = 2
4

4 回答 4

68

小部件无法访问 NSDocuments 目录,这是人们通常存储其数据库的地方。

解决方法是先创建一个App Group

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

命名容器,即'group.mycontainer'

使用与容器相同的名称对 Widget 的 Target 重复该过程。

然后将您的数据库写入您的组容器。

所以:

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]
于 2014-07-08T21:17:24.760 回答
7

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

请记住,如果您将持久性存储保存在应用组容器中,用户可能会在恢复 iOS 后丢失所有应用数据。

更新

rdar://18750178

更新

似乎在 iOS 8.1 中已修复,Apple 人员给我发消息并要求检查 iOS 8.1 中的问题是否已修复(不是很无礼吗?)。我没有测试过,所以请记住。无论如何,如果您支持有缺陷的 iOS 8.0,在 AppGroups 中保留存储是一个死主意

于 2014-09-18T12:45:59.763 回答
5

改变

[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];
}
于 2015-02-18T19:33:35.107 回答
1

斯威夫特也是如此:

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

于 2015-05-08T10:17:58.833 回答