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 中可以正常工作的主要内容,如果未能解决你的问题,请参考以下文章

在 OSX Mavrerick 中找不到 mvn 命令

错误:将实体添加到 CoreData 时“在实体中找不到键路径索引”

错误:在提供程序包中找不到类型“SingleChildCloneableWidget”

在 Flutter/Android 构建中找不到 protoc-3.9.2-osx

带有 Core Data 的 Cocoa pod 在消费应用程序中找不到实体

IntelliJ 编译时在同一个包中找不到类