5

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

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

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

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

提前致谢!

4

2 回答 2

5

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

然后您可以将捆绑网址传递给 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迁移点,因为在您迁移时包会发生变化。上面的文档很好地描述了它。

于 2011-12-11T18:01:31.477 回答
1

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

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

在我的 subclassedUIManagedDocument中,我重写该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];
}
于 2011-12-11T19:54:32.897 回答