【问题标题】:UIManagedDocument can only read documents that are file packagesUIManagedDocument 只能读取文件包的文档
【发布时间】:2011-12-09 13:50:57
【问题描述】:

我的应用正在使用核心数据 SQLite 数据库。我想让我的用户使用 iCloud 在设备之间同步它 - 我想我可以使用 UIManagedDocument。

我按照 Apple 的文档对其进行了子类化,当需要创建新的持久性存储文件时它可以工作。但是,当我尝试使用它打开旧的持久存储文件时,我收到以下异常抛出错误:

“UIManagedDocument 只能读取文件包的文档”

这是否意味着我需要将旧的持久存储迁移到由 UIManagedDocument 管理的新存储?如果是这样,我是否需要手动执行此操作(即从旧存储中一次读取每条记录并将其写入新存储)?

提前致谢!

【问题讨论】:

    标签: ios core-data icloud


    【解决方案1】:

    UIManagedDocument 创建包(文件夹)而不是原子存储。商店还在那儿,但它被埋在了包裹里。如果您右键单击模拟器中 Documents 文件夹中创建的文件,您将能够看到结构。默认为

    mydocument.foo
       -> StoreContent
          -> persistentStore
    

    您需要为您的应用文件类型创建一个新的扩展名,例如,如果您的数据库扩展名是.myappdb,您需要在项目设置中创建一个新的文档类型,它可能是.myappdbw。您可以从.myappdb 的条目中复制所有设置

    接下来,在您处理在mydocumenturl 打开旧文档而不是将其传递给持久存储协调器时,您将创建上面的目录结构。

    NSURL *newurl = [[mydocumenturl  URLByDeletingPathExtension] URLByAppendingPathExtension:@"myappdbw"];
    NSURL *desturl = [newurl URLByAppendingPathComponent:@"StoreContent"];
    [[NSFileManager defaultManager] createDirectoryAtURL:desturl withIntermediateDirectories:YES attributes:nil error:NULL];
    NSURL *finalurl = [desturl URLByAppendingPathComponent:@"persistentStore"];
    

    然后将旧数据库移动到您创建的文件夹系统中

    [[NSFileManager defaultManager] moveItemAtURL:mydocumenturl toURL:finalurl error:NULL];
    

    然后您可以将捆绑 url 传递给 UIManagedDocument

    UIManagedDocument *doc = [[UIManagedDocument alloc] initWithFileURL:newurl];
    

    对 iCloud 集成有用的链接是

    http://developer.apple.com/library/ios/#releasenotes/DataManagement/RN-iCloudCoreData/_index.html

    这有点神秘,因为大部分承诺的示例代码到目前为止都没有出现,但另一方面,它的推断大多相当简单。查看 WWDC2011 会议 107,116 和 315 以获得更多提示。

    但请注意,如果您打算使用此方法迁移旧文档不要在迁移时设置NSPersistentStoreUbiquitousContentNameKey,因为在您迁移时包会发生变化。上面的文档很好地描述了它。

    【讨论】:

      【解决方案2】:

      感谢您的提示。我想我找到了一个更简单的解决方案。

      我只是创建了一个新的UIManagedDocument,其文件名与我的旧持久存储位置不同。

      在我的子类UIManagedDocument 中,我覆盖了configurePersistentStoreCoordinatorForURL 方法并在那里进行迁移:

      - (BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)storeURL ofType:(NSString *)fileType modelConfiguration:(NSString *)configuration storeOptions:(NSDictionary *)storeOptions error:(NSError **)error
      {
          // If legacy store exists, copy it to the new location
          NSFileManager* fileManager = [NSFileManager defaultManager];
          if ([fileManager fileExistsAtPath:legacyPersistentStoreURL.path])
          {
              NSError* thisError = nil;
              [fileManager copyItemAtURL:legacyPersistentStoreURL toURL:storeURL error:&thisError];
              [fileManager removeItemAtURL:legacyPersistentStoreURL error:&thisError];
          }
      
          return [super configurePersistentStoreCoordinatorForURL:storeURL ofType:fileType modelConfiguration:configuration storeOptions:storeOptions error:error];
      }
      

      【讨论】:

      • 最好使用[fileManager replaceItemAtURL:storeURL withItemAtURL:legacyPersistentStoreURL backupItemName:nil options:NSFileManagerItemReplacementUsingNewMetadataOnly resultingItemURL:nil error:&thisError];而不是复制和删除,因为复制不会覆盖现有文件
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-31
      相关资源
      最近更新 更多