UIManagedDocument 只能读取文件包的文档

Posted

技术标签:

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

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

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

“”

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

提前致谢!

【问题讨论】:

【参考方案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];而不是复制和删除,因为复制不会覆盖现有文件

以上是关于UIManagedDocument 只能读取文件包的文档的主要内容,如果未能解决你的问题,请参考以下文章

使用 saveToURL:forSaveOperation:completionHandler 自动删除 UIManagedDocument 文件:

iOS使用UIManagedDocument添加初始核心数据文件,而不是appdelegate

UIManagedDocument 不保存到磁盘

覆盖UIManagedDocument中的managedObjectModel

无法创建 UIManagedDocument

UIManagedDocument 的迁移问题