it-swarm-ja.tech

iPhone用の静的ライブラリのコアデータ

CoreDataフレームワークを多用する静的ライブラリを構築しました。外部プロジェクトでライブラリを正常に使用できますが、メインプロジェクトに.xcdatamodelファイルを含めた場合に限ります。ライブラリの目的は実装の詳細を可能な限り隠すことだったので、これは理想的とは言えません。

別の 質問 で、リソースをライブラリにバンドルできないと通知されました(これは今では完全に理にかなっています)。

それで、メインプロジェクトにモデルを含めることなく、プログラムでモデルを「発見」できるようにする方法はありますか?

41
Vickram

また、CoreDataを使用する独自の静的ライブラリを作成しました。静的ライブラリに加えて、プロジェクトに別のバンドルターゲットがあり、バンドルリソースのコピーアイテムがあります。これは、いくつかの画像などをバンドルにコピーし、ソースのコンパイルフェーズでxcdatamodelをコンパイルします。

最終的なバンドルには、必要なすべてのファイルが含まれます。静的ライブラリに依存するメインプロジェクトでは、そのバンドルも含める必要があります。これで、メインプロジェクトはコアデータを使用するために必要なmomファイルにアクセスできるようになります。

バンドルの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;
}

バンドルを含めるだけで、xcdatamodelを提供する必要はなく、コンパイルされたmomファイルのみを含める必要があります。

31

Saschaの答えは私を正しい軌道に乗せました。コンパイルされた.momファイルを静的ライブラリから.momファイルにホストプロジェクトからマージするのは比較的簡単でした。簡単な例を次に示します。

  1. MyStaticLibraryという名前の新しいXCode静的ライブラリプロジェクトを作成します

  2. MyStaticLibraryModels.xcdatamodelという名前の.xcdatamodelファイルをMyStaticLibraryに作成し、いくつかのEntitysを追加してから、ヘッダーと実装を生成します。 MyStaticLibraryターゲットをビルドすると、libMyStaticLibrary.aバイナリファイルが生成されますが、コンパイルされた.momファイルは含まれません。そのためには、バンドルを作成する必要があります。

  3. Loadable Bundleの下にあるタイプMacOS X > Cocoaの新しいビルドターゲットを作成し、新しいターゲットMyStaticLibraryModelsを呼び出しましょう。

  4. MyStaticLibraryModels.xcdatamodelMyStaticLibraryModelsターゲットのCompile Sourcesビルドフェーズにドラッグします。 MyStaticLibraryModelsターゲットをビルドすると、MyStaticLibraryModels.bundleというファイルが生成され、コンパイルされたNSManagedObjectModelファイルMyStaticLibraryModels.momが含まれます。

  5. MyStaticLibraryターゲットとMyStaticLibraryModelsターゲットの両方をビルドした後、libMyStaticLibrary.a(および関連するModelヘッダーファイル)とMyStaticLibraryModels.bundleをホストプロジェクトMyAwesomeAppにドラッグします。

  6. MyAwesomeAppCoreDataを使用し、独自の.xcdatamodelファイルを持っており、独自のビルドプロセス中に.momファイルにコンパイルされます。この.momファイルをMyStaticLibraryModels.bundleにインポートしたファイルとマージします。 MyAwesomeAppプロジェクトのどこかに、MyAwesomeAppsNSManagedObjectModelを返すメソッドがあります。このメソッド用に生成されたAppleテンプレートは次のようになります:

.。

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

これを変更して、NSManagedObjectModels、MyAwesomApps、およびMyStaticLibraryModelsの両方を、次のように1つの結合された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_;
}

これにより、NSManagedObjectModelEntityの両方からMyAwesomeAppとマージされたMyStaticLibraryが返されます。

59
prairiedogg

Sascha Konietzkeのソリューションはうまく機能しますが、機能するために提供する必要のある重要な警告が1つあります。モデルを含むバンドルを最初にロードする必要があります。そうしないと、モデルは配列に含まれず、MOMにマージされません。

彼の場合、彼はおそらくすでにバンドルからリソースにアクセスしているため、このコードが実行される前にバンドルがすでにロードされています。

2
Spanner

いいえ、iPhoneアプリでApple以外のフレームワークを使用する際の制限により、OS Xと比較して依存関係ゲームが実際に変わります。ほとんどのiPhoneの「フレームワーク」(Mac用のGoogleのツールボックス、Core Plotなど)は実際には推奨 =製品(つまり静的ライブラリ)をリンクするのではなく、メインアプリケーションプロジェクトにソースを含めること。コミュニティのコンセンサスは、iPhoneでは、フレームワークの利用者がライブラリを使用するために少し「手動」の作業をしなければならないと予想しても問題ないと思います。あなたの場合、これはメインプロジェクトにxcdatamodelファイルを含めています。ほとんどのObjective-Cと同様に、実装の詳細を使用しないようにユーザーに指示し、そのままにしておきます。

2
Barry Wark

Prairiedoggの答えは少し時代遅れです。Xcode5でこれを行うためのチュートリアルは次のとおりです。 http://bharathnagarajrao.wordpress.com/2014/02/14/working-with-core-data-in-a-static -ライブラリ/

2
Liron Yahdav

coreDataを含むライブラリもあります。埋め込みリソースを使用してフレームワークを管理するためのこのテンプレートを見つけました

新しいプロジェクトで使用するのは本当に簡単です(既存のプロジェクトに適用するのはもっと難しいです)が、framewoksビルドの場合は本当にクールです:-)

https://github.com/kstenerud/iOS-Universal-Framework

2
Pixman