【问题标题】:Accessing Core Data SQL Database in iOS 8 Extension (Sharing Data Between App and Widget Extension)在 iOS 8 扩展中访问 Core Data SQL 数据库(在 App 和 Widget 扩展之间共享数据)
【发布时间】:2014-08-29 18:37:05
【问题描述】:

问题:

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

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

日志如下:

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

reason = "Failed to create file; code = 2

【问题讨论】:

    标签: ios iphone sqlite core-data ios-app-extension


    【解决方案1】:

    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

    【讨论】:

      【解决方案2】:

      改变

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

      【讨论】:

        【解决方案3】:

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

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

        更新

        rdar://18750178

        更新

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

        【讨论】:

        • 这是否记录在任何地方?
        • 标准备份程序是指通过 iTunes 备份,对吗?
        • @Awesome-o 都通过 iTunes 和 iCloud 进行备份。好像没有记录。根本找不到这方面的信息。
        • 这对我来说似乎是一个错误,让我们提交错误报告
        • 有 rdar id 可以欺骗吗?
        【解决方案4】:

        小部件无法访问 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]
        

        【讨论】:

        • 但是我如何获得协调员?我需要这个模型(momd)吗?如果是,我如何与扩展共享模型?
        • @BenjaminHerzog 您共享 momd 文件只需将其添加到扩展目标以及容器应用目标。
        • 我有点困惑如何让它在应用程序中工作?我可以在扩展程序中以这种方式使用 NSFileManager,但不能在主应用程序中使用。与扩展名不同,它返回 nil。
        • 如果包含的应用决定删除并重新创建持久存储,而扩展正在使用它会发生什么?
        • @Mark 数据迁移方案将如何工作?想象一下 ios 8 之前的应用程序将数据存储在原始 storeURL 中,现在新版本必须首先在新 storeURL 中创建新文件,然后以某种方式将原始数据迁移到新商店中。
        猜你喜欢
        • 2018-07-12
        • 1970-01-01
        • 1970-01-01
        • 2019-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多