43

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

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

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

4

8 に答える 8

59

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

  1. と呼ばれる新しいXCode静的ライブラリプロジェクトを作成しますMyStaticLibrary

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

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

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

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

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

..。

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

NSManagedObjectModelこれを変更して、 s、MyAwesomApps、およびの両方を1つとしてマージし、次のよう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_;
}

これにより、との両方からsとマージさNSManagedObjectModelれたものが返されます。EntityMyAwesomeAppMyStaticLibrary

于 2011-01-06T00:13:25.537 に答える
31

また、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ファイルのみを含める必要があります。

于 2009-11-14T13:37:13.990 に答える
2

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

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

于 2012-02-28T01:33:51.063 に答える
2

私もcoredataを備えたライブラリを持っています。リソースを埋め込んだフレームワークを管理するためのこのテンプレートを見つけました

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

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

于 2011-12-02T17:45:04.783 に答える
2

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

于 2014-07-31T16:59:10.870 に答える
2

xcdatamodel / momファイルを使用する代わりに、コードでモデルを作成することもできます(特に単純なモデルがある場合)。この方法では、リソース用の追加のバンドルを作成する必要はありません。これは、2つの属性を含む1つのテーブルを持つ簡単な例です。

- (NSManagedObjectModel *)coreDataModel
{
    NSManagedObjectModel *model = [NSManagedObjectModel new];

    NSEntityDescription *eventEntity = [NSEntityDescription new];
    eventEntity.name = @"EventEntity";
    eventEntity.managedObjectClassName = @"EventEntity";

    NSAttributeDescription *dateAttribute = [NSAttributeDescription new];
    dateAttribute.name = @"date";
    dateAttribute.attributeType = NSDateAttributeType;
    dateAttribute.optional = NO;

    NSAttributeDescription *typeAttribute = [NSAttributeDescription new];
    typeAttribute.name = @"type";
    typeAttribute.attributeType = NSStringAttributeType;
    typeAttribute.optional = NO;

    eventEntity.properties = @[dateAttribute, typeAttribute];
    model.entities = @[eventEntity];

    return model;
}

コードからモデルを作成する方法についてのチュートリアルは次のとおりです。https ://www.cocoanetics.com/2012/04/creating-a-coredata-model-in-code/

また、このアプローチに基づいて、LSMiniDBと呼ばれる、ニーズに合う可能性のある小さくて使いやすいライブラリを作成したので、それも確認できます。

また、私の場合、NSManagedObjectサブクラスのプロパティを使用しているときに、コンソールで「警告:動的アクセサーが@property実装を見つけられませんでした... 」などの警告が表示されました。これらのプロパティを別のファイルのカテゴリに入れるのではなく、クラスインターフェイス/実装に移動することで、これを修正できました(現在、xcodeはデフォルトで、このコードを別のファイルClassName+CoreDataClassとClassName+CoreDataPropertiesに分割して生成しています。および各サブクラスのカテゴリ)。

于 2017-10-09T16:18:58.953 に答える
1

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

于 2009-11-10T22:31:56.093 に答える
0

Saschaの答えのためのSwift2バージョン:

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.
    var allBundles = NSMutableSet()
    allBundles.addObjectsFromArray(NSBundle.allBundles())
    allBundles.addObjectsFromArray(NSBundle.allFrameworks())

    let model =  NSManagedObjectModel.mergedModelFromBundles(allBundles.allObjects as? [NSBundle])

    return model!
}()
于 2015-11-26T15:34:07.570 に答える