新项目中的 CoreData

Posted

技术标签:

【中文标题】新项目中的 CoreData【英文标题】:CoreData in new project 【发布时间】:2014-05-29 11:23:08 【问题描述】:

希望您能提供帮助。

我有一个 3 年前使用 CoreData 构建的 ios 应用。进行一些重大更新的机会出现了,人们认为在继续使用现有捆绑标识符的同时简单地启动一个新的 Xcode 项目更容易,这样应用程序仍然是 iTune 用户的实际更新。

我的问题是;在 Xcode 中创建一个新项目并从第一个版本手动创建模型/实体/属性的复制会阻止数据在新项目中可用吗?

我在应用程序的第一个版本中有一些快速代码,它只返回数据中的记录数(见下文),但是当在新项目中使用相同的代码时,它什么也不返回,就好像有应用程序中没有数据。 iCloud 也用于第一个版本。

我想如果我安装了应用程序的第一个版本,创建了一些记录,然后安装了新版本,数据仍然可用。

我是否误解了迁移如何与 CoreData 一起工作,我是否最好获取旧项目、重构 ARC 并手动移动新代码以便仍使用原始实体?

任何建议将不胜感激。

NSFileManager *fileManager = [NSFileManager defaultManager];

NSString *entityName = @"MyObjects";

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];

request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"row_id"
                                                                                 ascending:YES
                                                                                  selector:@selector(localizedCaseInsensitiveCompare:)]];

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyObjects" withExtension:@"mom"];

NSManagedObjectModel *managedObject = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

NSString *iCloudEnabledAppID = @"com.xxxx.myobjects";
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedObject];
NSString *dataFileName = @"MyObjects.sql";

NSString *iCloudDataDirectoryName = @"Data.nosync";
NSURL *iCloud = [fileManager URLForUbiquityContainerIdentifier:nil];

NSString *iCloudData = [[[iCloud path]
                         stringByAppendingPathComponent:iCloudDataDirectoryName]
                        stringByAppendingPathComponent:dataFileName];

NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:iCloudEnabledAppID            forKey:NSPersistentStoreUbiquitousContentNameKey];

[coordinator lock];

[coordinator addPersistentStoreWithType:NSSQLiteStoreType
                  configuration:nil
                            URL:[NSURL fileURLWithPath:iCloudData]
                        options:options
                          error:nil];

[coordinator unlock];

NSManagedObjectContext *moc = nil;
if (coordinator != nil) 
    moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    [moc setPersistentStoreCoordinator: coordinator];


NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                                    managedObjectContext:moc
                                                                      sectionNameKeyPath:nil
                                                                               cacheName:nil];
[fetchedResultsController performFetch:nil];

NSLog(@">>>>>> %@", [fetchedResultsController fetchedObjects]); // returns 2 records

【问题讨论】:

【参考方案1】:

首先,我不确定您为什么用 MagicalRecord 标记此内容。您的示例代码都是原始核心数据。

其次,如果我是你,我会从旧应用程序中获取现有模型文件,并将其作为新应用程序中数据模型的第一个版本。您可以使用属性和实体等重新创建数据模型,并最终得到相同版本的哈希值,但如果您已经有了起点,则无需经历这些麻烦.只需从现有数据模型开始并继续前进。 Xcode 和 Core Data 不会将数据模型文件绑定到 Xcode 项目,并且您没有任何锁定方式。托管对象模型文件与您应用中的所有其他代码一样只是文本文件。

第三,iCloud 设置在 iOS7 中需要的代码要少得多。这很简单,因为 Core Data 团队决定负责所有设置和备用存储的繁忙工作。我建议查看 WWDC2013 的“Core Data 中的新功能”演讲。

最后,您确定您实际上已将模型复制到现有商店吗?如果您的模型与存储不兼容,您的核心数据堆栈将不会附加持久存储。也就是说,从顶层(您的 NSManagedObjectContext)看,它似乎已初始化,但附加的 NSPersistentStoreCoordinator 将没有任何存储。如果没有存储,则不会保存任何数据,也不会加载任何数据。托管对象模型版本必须与存储文件中的版本信息匹配。您可以通过以下方式自行检查:

-[NSPersistentStoreCoordinator metadataForPersistentStore:]

+[NSPersistentStoreCoordinator metadataForPersistentStoreOfType:URL:error:]

结合

-[NSManagedObjectModel isConfiguration:compatibleWithStoreMetadata:]

您还提到了迁移。除非您拥有多个数据模型,否则您实际上并没有迁移数据。但是,当您确实有要迁移的版本时,您还需要为轻量级迁移(自动迁移)设置迁移选项,以便在将存储附加到协调器时执行操作。我建议阅读Apple Documentation on Versioning and Migration。

【讨论】:

假设可以访问旧项目,我会添加它。人们可能能够获得在分发中使用的实际持久存储(或至少接近近似值),否则即使管道完全正确,OP 也必须重建数据。 谢谢你们。在发布这篇文章后不久,我尝试从旧应用程序中获取数据模型并将其放入新应用程序中,但运气不佳。我将检查以确保我的持久存储也已被复制。为 MagicalRecord 标签道歉。我在项目中确实有 MagicalRecord,但在尝试解决它的最后几天我已经减少了它以尝试保持代码“原始”,只是为了消除 MagicalRecord 作为原因。再次感谢。

以上是关于新项目中的 CoreData的主要内容,如果未能解决你的问题,请参考以下文章

如何编辑保存在 CoreData 中的文本?

将 CoreData 添加到现有项目后出错

CoreData:按类别集中的索引对项目进行排序

如何正确更新详细视图中的 CoreData 对象?

NSBundle 中的 CoreData sqlite 文件

通过 UISearchBar 使用 CoreData 过滤查询