iPhone 静态库中的核心数据
我构建了一个大量使用核心数据框架的静态库。我可以在外部项目中成功使用该库,但前提是我在主项目中包含 .xcdatamodel 文件。这不太理想,因为该库的目的是尽可能隐藏实现细节。
在一个单独的问题中,我被告知我无法将资源与图书馆捆绑在一起(现在这对我来说完全有意义)。
那么有没有一种方法可以以编程方式允许“发现”模型,而不必将模型包含在主项目中?
I've built a static library that makes heavy use of the Core Data framework. I can successfully use the library in my external project, but ONLY if I include the .xcdatamodel file in the main project. That is less than ideal, since the point of the library was to hide implementation details to the maximum possible.
In a separate question, I was informed that I cannot bundle resources with a library (which makes complete sense to me now).
So is there a way to programatically allow the model to be 'discovered' without having to include the model in the main project?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
萨沙的回答让我走上了正轨。将静态库中已编译的
.mom
文件合并到宿主项目中的.mom
文件相对简单。这是一个简单的示例:创建一个新的 XCode 静态库
名为
MyStaticLibrary
的项目
在
MyStaticLibrary
中创建一个名为MyStaticLibraryModels.xcdatamodel
的 .xcdatamodel 文件,添加一些Entity
,然后生成标头和实现。构建MyStaticLibrary
目标时,您将生成一个libMyStaticLibrary.a
二进制文件,但它不会包含已编译的.mom
文件。为此,我们必须创建一个包。创建一个
Loadable Bundle
类型的新构建目标,可在MacOS X > 下找到。 Cocoa
,我们将新的 Target 命名为MyStaticLibraryModels
。将
MyStaticLibraryModels.xcdatamodel
拖到MyStaticLibraryModels
目标的Compile Sources
构建阶段。当您构建MyStaticLibraryModels
目标时,您将生成一个名为MyStaticLibraryModels.bundle
的文件,它将包含已编译的NSManagedObjectModel
文件,MyStaticLibraryModels .mom
。构建
MyStaticLibrary
和MyStaticLibraryModels
目标后,拖动libMyStaticLibrary.a
(以及任何关联的模型头文件)和MyStaticLibraryModels.bundle
到您的宿主项目MyAwesomeApp
中。MyAwesomeApp
使用CoreData
,有自己的.xcdatamodel
文件,该文件将在其自己的构建过程中编译成 .mom 文件。我们希望将此.mom
文件与我们在MyStaticLibraryModels.bundle
中导入的文件合并。在MyAwesomeApp
项目中的某个位置,有一个方法返回MyAwesomeApp
的NSManagedObjectModel
。 Apple 为此方法生成的模板如下所示:...
我们将更改此方法以合并并返回
NSManagedObjectModel
、MyAwesomApp
和MyStaticLibraryModels< /code>,作为单个组合的
NSManagedObjectModel
,如下所示:这将返回合并的
NSManagedObjectModel
以及来自两个MyAwesomeApp 的
和Entity
MyStaticLibrary
。Sascha's answer got me on the right track. Merging a compiled
.mom
file from a static library into the.mom
file from a host project was relatively simple. Here's a trivial example:Create a new XCode Static Library
project called
MyStaticLibrary
Create an .xcdatamodel file in
MyStaticLibrary
calledMyStaticLibraryModels.xcdatamodel
, add someEntity
s, then generate the headers and implementations. When you build theMyStaticLibrary
target, you'll generate alibMyStaticLibrary.a
binary file, but it won't include the compiled.mom
file. For that we have to create a bundle.Create a new build target of type
Loadable Bundle
, found underMacOS X > Cocoa
, let's call the new TargetMyStaticLibraryModels
.Drag
MyStaticLibraryModels.xcdatamodel
into theCompile Sources
build phase of theMyStaticLibraryModels
Target. When you build theMyStaticLibraryModels
Target, you will generate a file calledMyStaticLibraryModels.bundle
and it will contain the compiledNSManagedObjectModel
file,MyStaticLibraryModels.mom
.After building both the
MyStaticLibrary
andMyStaticLibraryModels
Targets, draglibMyStaticLibrary.a
(along with any associated Model header files) andMyStaticLibraryModels.bundle
into your host project,MyAwesomeApp
.MyAwesomeApp
usesCoreData
, has it's own.xcdatamodel
file which will get compiled into a .mom file during its own build process. We want to merge this.mom
file with the one we imported inMyStaticLibraryModels.bundle
. Somewhere in theMyAwesomeApp
project, there is a method that returnsMyAwesomeApp
sNSManagedObjectModel
. The Apple generated template for this method looks like this:...
We will alter this to merge and return BOTH of our
NSManagedObjectModel
s,MyAwesomApp
s andMyStaticLibraryModels
, as a single, combinedNSManagedObjectModel
like so:This will return the merged
NSManagedObjectModel
with theEntity
s from bothMyAwesomeApp
andMyStaticLibrary
.我还创建了自己的使用 Core Data 的静态库。除了静态库之外,我在项目中还有另一个捆绑目标,其中有一个“复制捆绑资源”项,它将一些图像和类似内容复制到捆绑中,以及一个“编译源”构建阶段,其中我正在编译 xcdatamodel。
最终的捆绑包将包含所有必需的文件。在依赖静态库的主项目中,您还必须包含该包。您的主项目现在可以访问使用核心数据所需的 mom 文件。
要使用捆绑包中的核心数据,您必须在代码中创建一个合并的托管对象模型(主项目可能也有一些核心数据模型):
通过仅包含捆绑包,您将不必给出xcdatamodel,只需要包含编译好的mom文件。
I also created my own static library that uses Core Data. Besides the static library I have a another bundle target in the project where I have a Copy Bundle Resources item, that copies some images and things like that into the bundle and a Compile Sources build phase, where I am compiling the xcdatamodel.
The final bundle will contain all the necessary files. In your main project that relies on the static library you have to include that bundle as well. Your main project will now have access to the mom file that is needed to use core data.
To use core data with the mom from the bundle you have to create a merged managed object model in your code (it might be the main project has some core data model as well):
By just including the bundle you will not have to give out the xcdatamodel, only the compiled mom file needs to be included.
我也有一些带有 coredata 的库。
我发现这个模板用于管理具有嵌入资源的框架,
在新项目上使用它非常简单(在现有项目上应用更困难)
但对于框架构建来说,它真的很酷:-)
https://github.com/kstenerud/iOS-通用框架
i have some library with coredata too.
i have found this template for manage a framework with embed ressources
it's really simple to use on a new project ( more difficult to apply on existing )
but for framewoks build, it's really cool :-)
https://github.com/kstenerud/iOS-Universal-Framework
Sascha Konietzke 的解决方案效果很好,但需要提供一个重要的警告才能使其发挥作用。包含模型的bundle需要先加载,否则不会包含在数组中并合并到MOM中。
在他的例子中,他可能已经访问了捆绑包中的资源,因此在执行此代码之前捆绑包已经加载。
Sascha Konietzke's solution works well, but there is one important caveat that needs to be provided for it to work. The bundle containing the model needs to be loaded first, otherwise it will not be included in the array and merged in the MOM.
In his case he has probably already accessed resources from the bundle therefore the bundle was already loaded prior to this code being executed.
Prairiedogg 的答案有点过时,这里有一个在 Xcode 5 中执行此操作的教程: http://bharathnagarajrao.wordpress.com/2014/02/14/working-with-core-data-in-a-static-library/
Prairiedogg's answer is a little outdated, here's a tutorial on doing this in Xcode 5: http://bharathnagarajrao.wordpress.com/2014/02/14/working-with-core-data-in-a-static-library/
请注意,您还可以在代码中创建模型(特别是如果您有一个简单的模型),而不是使用 xcdatamodel/mom 文件,这样您就不需要为资源创建额外的包。这是一个简单的示例,其中一个表包含两个属性:
这是有关从代码创建模型的教程:https://www.cocoanetics.com/2012/04/creating-a-coredata-model-in-code/
同样基于这种方法我创建了一个小型且易于使用的库,可能适合您的需求,称为 LSMiniDB,因此您也可以检查它。
同样在我的例子中,当使用 NSManagedObject 子类的属性时,我在控制台上收到诸如“警告:动态访问器无法找到 @property 实现...”之类的警告。我能够通过将这些属性移动到类接口/实现而不是将它们放在单独文件的类别中来解决这个问题(当前 xcode 默认情况下生成此代码,并将其拆分为单独的文件 ClassName+CoreDataClass 和 ClassName+CoreDataProperties )以及每个子类的类别)。
Note that instead of using xcdatamodel/mom file you can also create your model in code (especially if you have a simple model) and this way you won't need to create an additional bundle for resources. Here is a simple example with one table that contains two attributes:
Here is a tutorial about creating model from code: https://www.cocoanetics.com/2012/04/creating-a-coredata-model-in-code/
Also based on this approach I created a small and easy to use library that might fit your needs called LSMiniDB so you can check it also.
Also in my case I had warnings such as "warning: dynamic accessors failed to find @property implementation..." on the console while using properties of NSManagedObject subclasses. I was able to fix that by moving those properties to a class interface/implementation instead of having them in a category in a separate file (currently xcode by default is generating this code splited into separate files ClassName+CoreDataClass and ClassName+CoreDataProperties with a class and a category for each subclass).
不,在 iPhone 应用程序中使用非 Apple 框架的限制确实改变了相对于 OS X 的依赖游戏。大多数 iPhone“框架”(例如 Google 的 Mac 工具箱、Core Plot 等)实际上推荐 您将源代码包含在主应用程序项目中,而不是链接产品(即静态库)。我认为社区的共识是,在 iPhone 上,期望您的框架的使用者必须做一些“手动”工作才能使用您的库是可以接受的。就您而言,这包括主项目中的 xcdatamodel 文件。与大多数 Objective-C 一样,告诉你的用户不要使用实现细节,就这样吧。
No, the limitation on using non-Apple frameworks in an iPhone app really changes the dependency game relative to OS X. Most iPhone "frameworks" (e.g. Google's toolbox for Mac, Core Plot, etc.) actually recommend that you include the source in your main application project rather than linking a product (i.e. a static library). I think the community consensus is that, on iPhone, it's OK to expect consumers of your framework to have to do a little "manual" work to use your library. In your case, this is including the xcdatamodel file in the main project. As with most of Objective-C, tell your users not to make use of the implementation details and leave it at that.
Sascha 的回答的 Swift 2 版本:
Swift 2 version for Sascha's answer: