CoreData 在 OSX 框架包中找不到映射模型,但在 iOS 中可以正常工作
Posted
技术标签:
【中文标题】CoreData 在 OSX 框架包中找不到映射模型,但在 iOS 中可以正常工作【英文标题】:CoreData can't find mapping model in an OSX framework bundle, but works fine in iOS 【发布时间】:2010-09-07 02:07:00 【问题描述】:我有基于 CoreData 的数据层(使用 SQLite 数据存储),我在 ios 应用程序和 iOS 客户端与之通信的服务器上都使用它。数据层(objc 代码 + coredata 模型/映射定义)按照惯例编译到 iOS 包中,并编译到框架包中以在 OSX 上使用。
我正在使用映射模型进行默认迁移。
在 iOS 上,它运行良好。添加新数据模型版本后第一次在模拟器中运行应用程序时,它会根据标准 Apple 文档在您调用 addPersistentStoreWithType:configuration:...
时迁移所有数据。
在 OSX/PyObjC 上,它以 Persistent store migration failed, missing mapping model
失败,即由于某种原因,即使存在该捆绑包中也找不到映射模型 .cdm 文件。
如果您通过在包中查找它们来手动指定源/目标/映射模型,然后通过 NSMigrationManager 手动调用迁移,则一切正常,例如
bundle = objc.loadBundle( "MyApp_OSX", globals(),
os.path.join( base, FRAMEWORK_FILENAME ) )
# URLs of input and output datastores
datastoreURL = NSURL.fileURLWithPath_( datadir + "/MyApp.hsdb" )
outURL = NSURL.fileURLWithPath_( datadir + "/MyApp-migrated.hsdb" )
# URLs of old and new version MOMs and the mapping model
momd = bundle.URLForResource_withExtension_( "MyApp.momd", None )
url1 = momd.URLByAppendingPathComponent_( "MyApp 21.mom" )
url2 = momd.URLByAppendingPathComponent_( "MyApp 22.mom" )
mappingURL = bundle.URLForResource_withExtension_( "Test.cdm", None )
# Old and new MOMs and the mapping model
mom1 = NSManagedObjectModel.alloc().initWithContentsOfURL_( url1 )
mom2 = NSManagedObjectModel.alloc().initWithContentsOfURL_( url2 )
mm = NSMappingModel.alloc().initWithContentsOfURL_( mappingURL )
# Do the migration
migration = NSMigrationManager.alloc().initWithSourceModel_destinationModel_(
mom1, mom2 )
migration.migrateStoreFromURL_type_options_withMappingModel_toDestinationURL_destinationType_destinationOptions_error_(
datastoreURL, NSSQLiteStoreType, None, mm, outURL, NSSQLiteStoreType, None, None )
此时我不知道为什么 iOS 版本能够找到映射模型以成功迁移数据存储,但 OSX / PyObjC 版本却不能,尽管包中明确包含映射模型,并且映射模型显然是有效的,因为它在您手动调用它时起作用。
如果您能深入了解 CoreData 如何在捆绑包中搜索有效/适当的映射模型,这可能有助于确定如何在 OSX 上进行这项工作,我们将不胜感激。
【问题讨论】:
【参考方案1】:我会怀疑权限问题,因为这是 iOS 和 Cocoa 不同的一个领域,但由于硬编码 URL 有效,情况并非如此。它看起来像一个 NSBundle 问题。
我会先使用URLForResource:withExtension:
的标准格式,然后拆分名称和扩展名。这可能不是原因,但桥梁并不完美,您希望消除任何可能的来源错误。
如果您已确认该文件存在于捆绑包中,接下来检查它是否具有合理的路径。如果最终嵌套很深或路径名中有奇数字符,则 NSBundle 可能无法找到该文件。
【讨论】:
感谢 TZ 的回复。我尝试更改我的 Python 以拆分文件名的词干和扩展名,例如mappingURL = bundle.URLForResource_withExtension_( "Test", "cdm" )
并且它仍然在手动方法中工作,所以我认为文件扩展名检测没有问题。此外,cdm 文件位于捆绑包的基本Resources
目录中,所以我认为那里没有嵌套的事情。文件名中没有有趣的字符,所以我也不认为这是罪魁祸首。难倒!
另外 - 我检查了包中文件的权限,一切看起来都很正常。正如您所料,所有 .cdm 文件都处于模式 0644,所以我认为这不是权限问题。
最后一件事 - 我认为 PyObjC 桥不应该在这里发挥作用,因为对 NSPersistentStoreCoordinator#addPersistentStoreWithType:configuration:...
的实际调用是在 inside 我的 objc 方法中完成的已经实现,我从 Python 调用该方法,而不是直接调用 addPersistentStoreWithType
。因此,addPersistentStoreWithType
的调用上下文(至少就函数 arg 编组而言)在两种情况下都应该相同......
如果您对这个 TZ 有任何其他想法,只需检查一下?以上是关于CoreData 在 OSX 框架包中找不到映射模型,但在 iOS 中可以正常工作的主要内容,如果未能解决你的问题,请参考以下文章
错误:将实体添加到 CoreData 时“在实体中找不到键路径索引”
错误:在提供程序包中找不到类型“SingleChildCloneableWidget”
在 Flutter/Android 构建中找不到 protoc-3.9.2-osx