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