iPhone静态库中的核心数据

Vic*_*ram 41 iphone core-data static-libraries nsbundle

我已经构建了一个静态库,它大量使用了Core Data框架.我可以在我的外部项目中成功使用该库,但仅限于我在主项目中包含.xcdatamodel文件.这不太理想,因为库的要点是尽可能隐藏实现细节.

在一个单独的问题中,我被告知我无法将资源与库捆绑在一起(这对我来说完全合情合理).

那么有没有办法以编程方式允许模型被"发现",而不必将模型包含在主项目中?

Pra*_*ogg 59

Sascha的回答让我走上正轨.将.mom来自静态库的编译文件合并到.mom主机项目的文件中相对简单.这是一个简单的例子:

  1. 创建一个名为的新XCode静态库项目 MyStaticLibrary

  2. MyStaticLibrary被调用中创建一个.xcdatamodel文件MyStaticLibraryModels.xcdatamodel,添加一些Entitys,然后生成标题和实现.构建MyStaticLibrary目标时,您将生成libMyStaticLibrary.a二进制文件,但不包括已编译的.mom文件.为此,我们必须创建一个包.

  3. 创建一个类型的新构建目标Loadable Bundle,在下面找到MacOS X > Cocoa,让我们调用新的Target MyStaticLibraryModels.

  4. 拖动MyStaticLibraryModels.xcdatamodel到目标的Compile Sources构建阶段MyStaticLibraryModels.构建MyStaticLibraryModelsTarget时,您将生成一个名为的文件MyStaticLibraryModels.bundle,它将包含已编译的NSManagedObjectModel文件MyStaticLibraryModels.mom.

  5. 在构建MyStaticLibraryMyStaticLibraryModels目标之后,将libMyStaticLibrary.a(以及任何关联的模型头文件)拖动MyStaticLibraryModels.bundle到主机项目中MyAwesomeApp.

  6. MyAwesomeApp使用CoreData,拥有它自己的.xcdatamodel文件,它将在自己的构建过程中编译成.mom文件.我们想要将此.mom文件与我们导入的文件合并MyStaticLibraryModels.bundle.在MyAwesomeApp项目的某个地方,有一个返回MyAwesomeApps 的方法NSManagedObjectModel.Apple为此方法生成的模板如下所示:

...

- (NSManagedObjectModel *)managedObjectModel {
  if (managedObjectModel_ != nil) {
    return managedObjectModel_;
  }
  NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyAwesomeApp" withExtension:@"momd"];
  managedObjectModel_ = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];    
  return managedObjectModel_;
}
Run Code Online (Sandbox Code Playgroud)

我们将改变这个以合并并返回我们NSManagedObjectModelMyAwesomApps和s,并且MyStaticLibraryModels,作为单个,组合NSManagedObjectModel如下:

- (NSManagedObjectModel *)managedObjectModel {
  if (managedObjectModel_ != nil) {
    return managedObjectModel_;
  }

  NSMutableArray *allManagedObjectModels = [[NSMutableArray alloc] init];

  NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyAwesomeApp" withExtension:@"momd"];
  NSManagedObjectModel *projectManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
  [allManagedObjectModels addObject:projectManagedObjectModel];
  [projectManagedObjectModel release];

  NSString *staticLibraryBundlePath = [[NSBundle mainBundle] pathForResource:@"MyStaticLibraryModels" ofType:@"bundle"];
  NSURL *staticLibraryMOMURL = [[NSBundle bundleWithPath:staticLibraryBundlePath] URLForResource:@"MyStaticLibraryModels" withExtension:@"mom"];
  NSManagedObjectModel *staticLibraryMOM = [[NSManagedObjectModel alloc] initWithContentsOfURL:staticLibraryMOMURL];
  [allManagedObjectModels addObject:staticLibraryMOM];
  [staticLibraryMOM release];

  managedObjectModel_ = [NSManagedObjectModel modelByMergingModels:allManagedObjectModels];
  [allManagedObjectModels release];

  return managedObjectModel_;
}
Run Code Online (Sandbox Code Playgroud)

这将返回NSManagedObjectModelEntity两者MyAwesomeApp和s 合并的MyStaticLibrary.


Sas*_*zke 31

我还创建了自己的使用Core Data的静态库.除了静态库,我在项目中有另一个bundle目标,我有一个Copy Bundle Resources项,它将一些图像和类似的东西复制到bundle和Compile Sources构建阶段,我正在编译xcdatamodel.

最后一个包将包含所有必需的文件.在依赖于静态库的主项目中,您还必须包含该捆绑包.您的主项目现在可以访问使用核心数据所需的mom文件.

要使用来自bundle的mom的核心数据,你必须在代码中创建一个合并的托管对象模型(它可能是主项目也有一些核心数据模型):


- (NSManagedObjectModel *) mergedManagedObjectModel 
{   
    if (!mergedManagedObjectModel) 
    {
        NSMutableSet *allBundles = [[[NSMutableSet alloc] init] autorelease];
        [allBundles addObjectsFromArray: [NSBundle allBundles]];
        [allBundles addObjectsFromArray: [NSBundle allFrameworks]];

        mergedManagedObjectModel = [[NSManagedObjectModel mergedModelFromBundles: [allBundles allObjects]] retain];
    }

    return mergedManagedObjectModel;
}


只需包含bundle就不必给出xcdatamodel,只需要包含已编译的mom文件.

  • Sascha - 我知道你的答案已经有一段时间了,但我想知道你是否可以详细说明你如何设置目标和构建阶段,以便使用静态库的项目可以查看并包含已编译的mom文件.我目前正在构建一个使用CoreData的静态框架,我无法弄清楚如何做到这一点.我使用lipo将两个单独的.a文件(设备和模拟器版本)编译成一个静态库包. (8认同)