多次通过核心数据迁移的示例或说明?

我的iPhone应用程序需要迁移其核心数据存储,并且某些数据库非常大。苹果的文档建议使用“多次通过”来迁移数据以减少内存使用。但是,文档非常有限,并且不能很好地说明如何实际执行此操作。有人可以为我指出一个好的例子,还是详细说明如何真正实现这一目标的过程?


浮云间
浏览 588回答 3
3回答

米琪卡哇伊

我已经弄清楚了Apple在其文档中的提示。实际上,这很容易,但要走很长的路要走。我将通过一个示例来说明该解释。初始情况是这样的:数据模型版本1这是使用“带有核心数据存储的基于导航的应用程序”模板创建项目时获得的模型。我编译了它,并在for循环的帮助下进行了一些重创,以创建大约2k个条目,每个条目都有一些不同的值。在那里,我们以NSDate值进行了2.000个事件。现在,我们添加数据模型的第二个版本,如下所示:数据模型版本2区别在于:事件实体不见了,我们有了两个新实体。一个将时间戳记存储为a double,第二个将时间戳记存储为NSString。目标是将所有版本1事件转移到两个新实体,并在迁移过程中转换值。这将导致值的两倍,每个值在单独的实体中作为不同的类型。要进行迁移,我们选择手动迁移,而映射模型就是这样做。这也是您问题答案的第一部分。我们将分两步进行迁移,因为迁移2k条目需要花费很长时间,并且我们希望保持较低的内存占用。您甚至可以继续拆分这些映射模型,以仅迁移实体范围。假设我们有100万条记录,这可能会使整个过程崩溃。使用Filter谓词可以缩小获取的实体的范围。回到我们的两个映射模型。我们创建第一个映射模型,如下所示:1.新建文件->资源->映射模型 2.选择一个名称,我选择了StepOne3.设置源和目标数据模型映射模型第一步多遍迁移不需要自定义实体迁移策略,但是我们将为该示例提供更多细节。因此,我们向实体添加了自定义策略。这始终是的子类NSEntityMigrationPolicy。该策略类实现了一些使迁移发生的方法。但是,在这种情况下很简单,因此我们只需要实现一种方法:createDestinationInstancesForSourceInstance:entityMapping:manager:error:。该实现将如下所示:StepOneEntityMigrationPolicy.m#import "StepOneEntityMigrationPolicy.h"@implementation StepOneEntityMigrationPolicy- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance                                       entityMapping:(NSEntityMapping *)mapping                                             manager:(NSMigrationManager *)manager                                               error:(NSError **)error{    // Create a new object for the model context    NSManagedObject *newObject =         [NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName]                                       inManagedObjectContext:[manager destinationContext]];    // do our transfer of nsdate to nsstring    NSDate *date = [sInstance valueForKey:@"timeStamp"];    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];    [dateFormatter setTimeStyle:NSDateFormatterMediumStyle];    [dateFormatter setDateStyle:NSDateFormatterMediumStyle];        // set the value for our new object    [newObject setValue:[dateFormatter stringFromDate:date] forKey:@"printedDate"];    [dateFormatter release];    // do the coupling of old and new    [manager associateSourceInstance:sInstance withDestinationInstance:newObject forEntityMapping:mapping];    return YES;}最后一步:迁移本身我将跳过设置几乎完全相同的第二个映射模型的部分,只是将NSDate转换为double的timeIntervalSince1970。最后,我们需要触发迁移。我现在暂时跳过样板代码。如果您需要,我会在这里发布。可以在“ 定制迁移过程”中找到它,它只是前两个代码示例的合并。如下第三和最后一部分将被修改:除了使用的类方法的NSMappingModel类mappingModelFromBundles:forSourceModel:destinationModel:,我们会使用initWithContentsOfURL:,因为该类方法将返回只有一个,也许是第一次,发现映射模型的捆绑。现在,我们有了两个映射模型,它们可以在循环的每个过程中使用,并将迁移方法发送到迁移管理器。而已。NSArray *mappingModelNames = [NSArray arrayWithObjects:@"StepOne", @"StepTwo", nil];NSDictionary *sourceStoreOptions = nil;NSURL *destinationStoreURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataMigrationNew.sqlite"];NSString *destinationStoreType = NSSQLiteStoreType;NSDictionary *destinationStoreOptions = nil;for (NSString *mappingModelName in mappingModelNames) {    NSURL *fileURL = [[NSBundle mainBundle] URLForResource:mappingModelName withExtension:@"cdm"];    NSMappingModel *mappingModel = [[NSMappingModel alloc] initWithContentsOfURL:fileURL];    BOOL ok = [migrationManager migrateStoreFromURL:sourceStoreURL                                               type:sourceStoreType                                            options:sourceStoreOptions                                   withMappingModel:mappingModel                                   toDestinationURL:destinationStoreURL                                    destinationType:destinationStoreType                                 destinationOptions:destinationStoreOptions                                              error:&error2];    [mappingModel release];} 笔记映射模型以cdm捆绑包结尾。必须提供目标存储,并且不应将其作为源存储。成功迁移后,您可以删除旧的并重命名新的。创建映射模型后,我对数据模型进行了一些更改,这导致了一些兼容性错误,我只能通过重新创建映射模型来解决。

qq_花开花谢_0

这些问题相关:在iPhone上迁移大型CoreData数据存储时出现内存问题iOS多通道核心数据迁移引用第一个链接:官方文档的“多次通过”部分对此进行了讨论,但是看起来他们建议的方法是按实体类型划分迁移,即制作多个映射模型,每个映射模型都从实体模型中迁移实体类型的子集。完整的数据模型。
打开App,查看更多内容
随时随地看视频慕课网APP