CoreData 在 OSX 框架包中找不到映射模型,但在 iOS 中工作正常

发布于 2024-09-18 11:29:07 字数 1857 浏览 11 评论 0原文

我有基于 CoreData 的数据层(使用 SQLite 数据存储),我在 iOS 应用程序和 iOS 客户端与之通信的服务器上使用它。数据层(objc 代码 + coredata 模型/映射定义)照常编译到 iOS 包中,并编译到框架包中以在 OSX 上使用。

我在使用映射模型的默认迁移方面遇到了困难。

在 iOS 上,它运行良好。添加新数据模型版本后首次在模拟器中运行应用程序时,当您根据标准 Apple 文档调用 addPersistentStoreWithType:configuration:... 时,它会迁移所有数据。

在 OSX / PyObjC 上,它会失败,并显示持久存储迁移失败,缺少映射模型,即由于某种原因,即使存在映射模型 .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 上进行这项工作,我们将不胜感激。

I have CoreData-based data layer (using a SQLite datastore) that I am using in both an iOS app and on the server that the iOS clients talk to. The data layer (objc code + coredata model / mapping defns) is compiled into the iOS bundle as per usual, and is compiled into a Framework bundle for use on OSX.

I am hitting a brick wall with default migration using mapping models.

On iOS, it works fine. The first time running the app in the simulator after adding the new datamodel verison, it migrates all the data when you call addPersistentStoreWithType:configuration:... as per the standard Apple docs.

On OSX / PyObjC, it fails with Persistent store migration failed, missing mapping model, i.e. for some reason the mapping model .cdm file can't be found in that bundle even though it is present.

If you manually specify the source / dest / mapping models by looking them up in the bundle and then manually invoke a migration through a NSMigrationManager, everything works fine, e.g.

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 )

At this point I have no idea why the iOS version is able to find the mapping model to successfully migrate the datastore but the OSX / PyObjC version can't, despite clearly having the mapping model in the bundle, and the mapping model apparently being valid since it works when you invoke it manually.

Any insight into how CoreData searches for valid / appropriate mapping models in bundles that might help identify how to make this work on OSX would be much appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

昇り龍 2024-09-25 11:29:07

我曾怀疑存在权限问题,因为这是 iOS 和 Cocoa 不同的地方,但由于硬编码 URL 有效,事实并非如此。看起来像是 NSBundle 问题。

我将首先使用标准形式的 URLForResource:withExtension: 并将名称和扩展名分开。这可能不是原因,但桥并不完美,您希望消除任何可能的源错误。

如果您确认该文件存在于捆绑包中,接下来检查它是否具有合理的路径。如果您最终嵌套得很深或路径名中包含奇数字符,NSBundle 可能无法找到该文件。

I would have suspected a permissions problem because that is one area where iOS and Cocoa differ but since the hard coded URL works, that is not the case. It looks like an NSBundle problem.

I would start by using the standard form of URLForResource:withExtension: and split up the name and extension. It' probably not the cause but the bridge is not perfect and you want to eliminate any possible sources errors.

If you've confirmed that file exist in the bundle, next check that it has a reasonable path. If you end up nesting to deep or with odd characters in path names, NSBundle may not locate the file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文