如何从 iOS 静态库中访问 Bundle

Posted

技术标签:

【中文标题】如何从 iOS 静态库中访问 Bundle【英文标题】:How to access Bundle from iOS static library 【发布时间】:2015-02-14 21:50:47 【问题描述】:

我正在使用 Core Data 框架开发一个静态库。遗憾的是,我无法访问我生成的 Bundle / .momd 文件。

我做了什么:

创建我的数据模型(Model.xcdatamodeld 文件) 创建一个新的 Bundle 目标(名为 sdkResources),我已在 Compile Sources 中添加了我的 xcdatamodeld 文件并链接了 CoreData.framework 在我的 sdk 目标中,我已将 sdkResources.bundle 放在“复制捆绑资源”部分中 编辑我的 sdk 方案并在构建部分添加 sdkResources 目标

我不工作的代码:

NSString *staticLibraryBundlePath = [[NSBundle mainBundle] pathForResource:@"sdkResources" ofType:@"bundle"];
NSURL *staticLibraryMOMURL = [[NSBundle bundleWithPath:staticLibraryBundlePath] URLForResource:@"Model" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:staticLibraryMOMURL];

返回:

[FAILED], NSInvalidArgumentException "Cannot create an NSPersistentStoreCoordinator with a nil model" raised

问题似乎是“mainBundle”访问,因为当我运行我的 sdk 测试时,下面的代码正在运行(至少没有错误)

NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSURL *staticLibraryMOMURL = [bundle URLForResource:@"Model" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:staticLibraryMOMURL];

但是当我想在另一个应用程序中使用我的 sdk(使用 podFile 文件)时,我无法访问我的包并得到相同的错误:/

我已经阅读并尝试了很多,但似乎没有任何效果。我在 ios 开发方面没有太多经验,我正在尽力了解发生了什么,但现在对我来说这是一条死胡同:(

问候

编辑/我的项目配置屏幕

我不知道为什么 sdkResources.bundle 是红色的.. 希望这是您的要求,谢谢。

编辑:修复 sdkResources.bundle 的路径后

编辑:

好的,我真的很接近解决方案了,我的包已成功复制到我的最终应用程序中,但我无法访问我的模型,并且它仅在我使用 [NSBundle bundleForClass:[self class]] 而不是 [NSBundle mainBundle]。这可能只是一个愚蠢的配置,但是..是的..我会继续挖掘!

【问题讨论】:

1.如果包被复制成功,请在查找器中检查 2.NSLog为staticLibraryBundlePath返回的路径 3.NSLog staticLibraryMOMURL 检查是否正常 遗憾的是,我在最终的应用程序中找不到我的 sdkResources.bundle 的任何痕迹。我应该在哪里找到它以及正确复制它的过程是什么?在我不工作的情况下,我的 staticLibBundlePath 和 MOMRUL 都是空的。 在验证您确实将 xcode 复制到正确的目标时制作 xcode 的图片。检查检查器选项卡并检查目标副本构建阶段 【参考方案1】:

好的,我明白了!

在(太多)小时搜索将我的模型放入 Bundle 之后,我决定将其保留在我的 sdk 中并检查我的 podspec 配置(因为它在我的 sdk 测试中有效,但在我的最终项目中没有)

这是我的解决方案,在我刚刚添加的 podspec 文件中:

s.resources      = 'sdk/**/*.xcdatamodeld,xcdatamodel'
s.preserve_paths = 'sdk/**/*'
s.framework = 'CoreData'

基本上,我只是将我的模型添加为资源和 CoreData 框架。至少我学到了很多关于 Bundle 和 podspec 配置的知识……

【讨论】:

【参考方案2】:

如果它是红色的,则该文件不存在。如果您确定它存在,请删除红色文件并重新添加:这可能是一个错误配置的文件链接

编辑添加:通常,您必须先构建库才能生成文件。这个库有目标吗?如果是这样,请选择它,构建然后切换回您的项目

【讨论】:

当我创建了我的 Bundle 目标时,Xcode 在我的“Products”组中生成了一个“sdkResources.bundle”文件,但即使在成功构建了我的 bundle 之后,其中的所有内容似乎都丢失了。是的,我有我的 sdk 和我的包的目标。我的 sdk 需要 bundle 才能工作。 文件是否存在于您假设的位置?如果是,请链接到它。红色链接表示文件未找到 确实如此,当我单击产品组中的 sdkResources.bundle 时,我可以看到正确的“完整路径”属性!我如何链接到它(因为它已经正确..)?我无法控制“产品组”中的文件(删除、添加......)对不起,我现在感觉很迟钝...... 删除红色链接的项目,将好的项目拖到同一个窗口中。 好的,我真的很接近解决方案(我认为......)当我在“复制捆绑资源”构建阶段手动添加我的 sdkResources.bundle 时,它​​会在我的 SDK 文件树中“弹出”但是 [[NSBundle mainBundle] pathForResource:@"sdkResources" ofType:@"bundle"] 仍然返回 null :/【参考方案3】:

从屏幕截图中我们看到,虽然捆绑包是要被复制的,但它并不存在。 => 没关系,以后可能会建

但是

我们也可以看到 sdk 目标不依赖于 sdkResoures。 捆绑包没有及时构建

将其设置为在方案中构建是不行的(方案为时已晚!)目标需要依赖于捆绑目标

【讨论】:

好的,我明白了。我已经在我的 sdk 目标的“目标依赖项”中添加了 sdkResources,但除了在我的 sdkTests 中之外它仍然无法工作:/我是否错过了其他东西?例如,我是否需要在我的 podspec 文件中设置一些内容?【参考方案4】:

我认为如果您不使用 Pod 并且仅使用框架,解决方案可能会简单得多。 您将不得不更改您正在寻找您的momd 中的Bundle

请查看这篇文章here

提出的解决方案是

    lazy var managedObjectModel: NSManagedObjectModel = 
    // The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
    let carKitBundle = NSBundle(identifier: "com.andrewcbancroft.CarKit")

    let modelURL = carKitBundle!.URLForResource("CarModel", withExtension: "momd")!
    return NSManagedObjectModel(contentsOfURL: modelURL)!
()

这里com.andrewcbancroft.CarKit 是您框架的包标识符,即包含您要从代码中访问的momd 文件的包

【讨论】:

以上是关于如何从 iOS 静态库中访问 Bundle的主要内容,如果未能解决你的问题,请参考以下文章

从bundle中加载xib

如何在iOS的静态库中添加xib文件

静态库中的对话框资源

Friend函数访问静态库中定义的类的私有成员

IOS开发中制作属于自己的静态库.a资源库.bundle.framework

当 iOS 应用程序链接到静态库时,如何获取丢弃的符号列表?