cho*_*rry 45 cocoa core-data objective-c nspersistentdocument osx-lion
我正在尝试在Core Data中轻量迁移SQLite存储.使用Xcode 4.3.1在Lion 10.7.3上工作.
在我的NSPersistentDocument子类(AccountDocument)中,我重写了用于配置持久性存储协调器的方法,以便它为迁移获取正确的选项:
- (BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url ofType:(NSString *)fileType modelConfiguration:(NSString *)configuration storeOptions:(NSDictionary *)storeOptions error:(NSError **)error
{
NSMutableDictionary *newStoreOptions;
if (storeOptions == nil) {
newStoreOptions = [NSMutableDictionary dictionary];
}
else {
newStoreOptions = [storeOptions mutableCopy];
}
[newStoreOptions setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[newStoreOptions setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
BOOL result = [super configurePersistentStoreCoordinatorForURL:url ofType:fileType modelConfiguration:configuration storeOptions:newStoreOptions error:error];
return result;
}
Run Code Online (Sandbox Code Playgroud)
(感谢Malcolm Crawford的提示:http://homepage.mac.com/mmalc/CocoaExamples/controllers.html)
当我运行应用程序时,它在NSPersistentDocument的实现中失败-managedObjectModel
:
* thread #1: tid = 0x2703, 0x00007fff931d9350 libobjc.A.dylib`objc_msgSend_vtable13 + 16, stop reason = EXC_BAD_ACCESS (code=13, address=0x0)
frame #0: 0x00007fff931d9350 libobjc.A.dylib`objc_msgSend_vtable13 + 16
frame #1: 0x00007fff8935e975 CoreData`-[NSKnownKeysDictionary1 _setValues:retain:] + 197
frame #2: 0x00007fff8935f288 CoreData`_newReadModelFromBytes + 648
frame #3: 0x00007fff8935b93e CoreData`+[NSManagedObjectModel(_NSManagedObjectModelPrivateMethods) _newModelFromOptimizedEncoding:error:] + 9310
frame #4: 0x00007fff89359451 CoreData`-[NSManagedObjectModel(_NSManagedObjectModelPrivateMethods) initWithContentsOfOptimizedURL:] + 305
frame #5: 0x00007fff89358d7b CoreData`-[NSManagedObjectModel initWithContentsOfURL:] + 443
frame #6: 0x00007fff893e9519 CoreData`+[NSManagedObjectModel mergedModelFromBundles:] + 377
frame #7: 0x00007fff8ded7037 AppKit`-[NSPersistentDocument managedObjectModel] + 301
frame #8: 0x00007fff8ded70b3 AppKit`-[NSPersistentDocument managedObjectContext] + 75
frame #9: 0x00007fff8ded6e3f AppKit`-[NSPersistentDocument _persistentStoreCoordinator] + 18
frame #10: 0x00007fff8ded6b5d AppKit`-[NSPersistentDocument configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:] + 51
frame #11: 0x0000000100003193 BeanCounter`-[AccountDocument configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:] + 419 at AccountDocument.m:298
Run Code Online (Sandbox Code Playgroud)
从我从文档中可以看出,默认实现看起来像这样:
- (id)managedObjectModel
{
NSManagedObjectModel *result = [NSManagedObjectModel mergedModelFromBundles:nil];
return result;
}
Run Code Online (Sandbox Code Playgroud)
所以为了更多地调试这个问题,我用这个方法覆盖了那个方法:
- (id)managedObjectModel
{
NSBundle *bundle = [NSBundle mainBundle];
NSURL *url = [bundle URLForResource:@"AccountDocument2" withExtension:@"momd"];
NSManagedObjectModel *result = [[[NSManagedObjectModel alloc] initWithContentsOfURL:url] autorelease];
return result;
}
Run Code Online (Sandbox Code Playgroud)
(感谢Jeff LaMarche的想法:http://iphonedevelopment.blogspot.com/2009/09/core-data-migration-problems.html)
bundle和url都指向我期望的位置(我遵循Marcus Zarra的建议来清理项目,因此应用程序包中没有任何杂散的.mom或.momd包:使用mergedModelFromBundles:和版本控制(CoreData)).然而,当从网址加载模型时,应用程序继续崩溃.
我已经检查过AccountDocument2.xcdatamodeld是一个包含两个版本控制模型的包:AccountDocument 2.xcdatamodel和(原始)AccountDocument.xcdatamodel.文件属性中的"Versioned Core Data Model"弹出菜单设置为"AccountDocument 2".
两个模型之间的唯一区别是一个实体具有附加(和可选)属性.我的理解是使模型符合轻量级迁移的要求.
显然,我在这里做错了,但我不知道是什么.非常感激任何的帮助…
更新:
根据Martin的建议(以及对NSPersistentDocument文档的检查),我尝试将此代码用于访问者:
- (id)managedObjectModel
{
static id sharedManagedObjectModel = nil;
if (sharedManagedObjectModel == nil) {
NSBundle *bundle = [NSBundle mainBundle];
NSURL *url = [bundle URLForResource:@"AccountDocument2" withExtension:@"momd"];
sharedManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:url];
}
return sharedManagedObjectModel;
}
Run Code Online (Sandbox Code Playgroud)
还在崩溃......
更新
在推特上提出一些建议之后,我升级到了Xcode 4.3.2,但问题仍然存在.
RAGE UPDATE
我刚刚在Snow Leopard上使用Xcode 4.2创建了版本化的模型包(AccountDocument2.xcdatamodeld).构建并运行应用程序后,一切都按预期工作.
然后我将AccountDocument2.xcdatamodeld文件包重新带回Lion和Xcode 4.3.2.当我构建并运行应用程序时,它会在加载.momd资源时继续崩溃.是的孩子,这意味着Xcode 4.3.x和数据模型编译器(MOMC)应该受到指责.除了在Snow Leopard上进行所有构建之外,我没有看到解决方法.
我不是一个打击Xcode 4的人,但是当我们发现自己处于工具链无法从不透明的规范(.xcdatamodel和.xcdatamodeld)生成不透明文件(.mom和.momd)的情况时,我很难对Mac和iOS工具的状态持乐观态度.这些平台的核心组件突破到我无法在最新版本的SDK和开发人员工具上构建和运行我的应用程序,这是荒谬的.
它来到这个更新
更多证明这是Xcode 4.3.2中数据模型编译器(MOMC)的一个严重错误:如果我将.momd包从Xcode 4.2创建的Resource文件夹复制到我的项目中,并将它们作为复制文件添加到构建中构建阶段,应用程序工作正常.
我还做了一些测试,我删除了各个实体的属性的验证规则和默认值(基于Marcus的建议).没有变化,编译器仍然创建一个无效的.momd.我还尝试创建一个版本化的模型,其中NOTHING被更改:编译的.momd继续崩溃.因此,无论您在当前模型(以及它们所代表的数据)中拥有什么,都是问题的根源.
另外值得注意的是:这个bug并没有被隔离到NSPersistentDocument(就像我最初想的那样,当我开始这个问题时.)我可以通过使用来导致应用程序崩溃[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]
.
现在,我将使用Snow Leopard上的Xcode 4.2编辑/版本化我的模型,并将已编译的资源移到Lion上的Xcode 4.3.2.如果您以任何方式使用Core Data,我建议您在解决此错误之前执行相同的操作.相信我,如果你不这样做,你会花几天的时间试图弄清楚到底发生了什么.
现在提交雷达......
雷达更新
我刚刚提交了这个雷达:
http://www.openradar.me/11184500
哦,废话必须是狮子更新
我刚从http://developer.apple.com/downloads下载并安装了适用于Lion工具的Xcode 4.2 .雷达中使用的示例应用程序仍然崩溃.
(注意:您无法安装Xcode 4.2.1,因为用于签署DeveloperTools.pkg的证书已过期.只有Xcode 4.2才有效.)
如果你在NDA下,你也会发现beta工具也没有帮助.
希望你有一个Snow Leopard的副本和Xcode 4.2坐在一起:http://furbo.org/2012/03/28/vmware-for-developers/
WTF提取请求与版本化实体和属性更新有关
通过推特上的Evadne Wu:
https://twitter.com/#!/evadne/status/187625192342818818
她是怎么做到的:
https://twitter.com/#!/evadne/status/187629091518816258
(.mom文件是二进制plists.)
问题的根源是单个获取请求.如何将数据从一种模型迁移到另一种模型,这是苹果公司的工程师要弄清楚的.
cho*_*rry 11
在"existingPartner"获取请求从以下位置更改后,可以加载已编译的.momd资源:
name == $name
Run Code Online (Sandbox Code Playgroud)
至:
name == $NAME
Run Code Online (Sandbox Code Playgroud)
这是违反直觉的,不影响数据持久性的对象模型的一部分会破坏版本控制和轻量级迁移.从文档中可以清楚地看出,情况并非如此:
Core Data对版本控制的看法是它只对影响持久性的模型特征感兴趣.
使用CHOCKLOCK的强大功能来修复您的获取请求或完全删除它们并依赖于在代码中创建的NSPredicates.
归档时间: |
|
查看次数: |
5526 次 |
最近记录: |