web-dev-qa-db-ja.com

フレームワーク内でコアデータ管理オブジェクトモデルを使用する方法

私は自分のアプリの特定の部分をフレームワークに移行して、自分のアプリ自体とそれらの豪華な新しいiOS 8ウィジェットの1つで使用できるようにしています。この部分は、Core Data内のすべてのデータを処理する部分です。すべてを移動してアクセスするのは簡単です。そこにあるmomdファイルへのアクセスに問題があります。

NSManagedObjectModelを作成するときも、Appleのコードテンプレートに示されているように、momdをロードしようとします。

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyApp" withExtension:@"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

残念ながら、modelURLnilのままなので、このエラーでCore DataスタックにアクセスするとMyAppがクラッシュします。

2014-08-01 22:39:56.885 MyApp[81375:7417914] Cannot create an NSPersistentStoreCoordinator with a nil model
2014-08-01 22:39:56.903 MyApp[81375:7417914] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot create an NSPersistentStoreCoordinator with a nil model'

それで、Core Dataを使用してフレームワーク内で作業するときにこれを行う正しい方法は何ですか?

31
flohei

私はfloheiの問題に少し遅れますが、うまくいけば、これが他の人が迷うのを助けるでしょう。これを機能させるには、script-fuを実行してリソースをコピーする必要はありません。

デフォルトでは、Appleのコアデータテンプレートは次のようなものを提供します。

lazy var managedObjectModel: NSManagedObjectModel = {
  let modelURL = NSBundle.mainBundle().URLForResource("MyCuteCoreDataModel", withExtension: "momd")!
  return NSManagedObjectModel(contentsOfURL: modelURL)!
}()

これにより、メインバンドルからコアデータリソースが読み込まれます。ここで重要なのは、Core Dataモデルがフレームワークにロードされている場合、。momdファイルはそのフレームワークのバンドルにあるです。したがって、代わりにこれを行うだけです。

lazy var managedObjectModel: NSManagedObjectModel = {
    let sexyFrameworkBundleIdentifier = "com.heybaby.xxx"
    let customKitBundle = NSBundle(identifier: sexyFrameworkBundleIdentifier)!
    let modelURL = customKitBundle.URLForResource("MyCuteCoreDataModel", withExtension: "momd")!
    return NSManagedObjectModel(contentsOfURL: modelURL)!
}()

これで問題なく動作するはずです。

クレジット: https://www.andrewcbancroft.com/2015/08/25/sharing-a-core-data-model-with-a-Swift-framework/

23
Jonathan Zhan

Xcdatamodeldファイルをドラッグして、ビルドフェーズにドロップする必要があります。フレームワークを使用するターゲットのソースをコンパイルします。次に、ターゲットを実行すると、その[NSBundle mainBundle]にモデル(momdファイル)が含まれます。

13
user3771857

@Ric Santosはほとんどそこにいた。私はそれを「momd」ではなく「mom」拡張にするだけで十分だと思います。そうすれば実行されます。

lazy var managedObjectModel: NSManagedObjectModel = {
    let modelURL = NSBundle(forClass: self.dynamicType.self).URLForResource(self.dataModelName, withExtension: "mom")!
    return NSManagedObjectModel(contentsOfURL: modelURL)!
}()
6
Faqinghere

私はこれに答えるのが少し遅れるかもしれませんが、これが私の問題を解決したものです:

私のフレームワークでは、画像やその他のリソースなどのバンドルも提供しています。 xcdatamodeldファイルを置くと、このファイルがプロジェクトでビルドされるため、何も得られず、結果としてアプリバンドル内のmomdフォルダー(実際にはこのケースにはありません)。別のターゲットを作成しましたが、フレームワークではなく、アプリを作成し、アプリバンドルからmomdをコピーしました。プロジェクト内の別のバンドル(フレームワークに対応するもの)。これを行った後は、リソースのURLをメインバンドルから新しいバンドルに変更するだけです。

// ...
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"separate_bundle" ofType:@"bundle"];
NSURL *modelURL = [[NSBundle bundleWithPath:bundlePath] URLForResource:@"your_model" withExtension:@"momd"];
// ...

私にとってはうまくいきました。私が知っている唯一のことは、まだ知らなかったApp Store Reviewです。より良い解決策を見つけた場合は、共有してください。

[〜#〜]編集[〜#〜]

より良いソリューションが見つかりました。自分でモデルを作成できます。 コアデータプログラミングガイド

データモデルはデプロイメントリソースです。モデルのエンティティとプロパティの詳細に加えて、Xcodeで作成するモデルには、ダイアグラムに関する情報(レイアウト、要素の色など​​)が含まれています。この後者の情報は、実行時には必要ありません。モデルファイルは、モデルコンパイラーmomcを使用してコンパイルされ、無関係な情報を削除し、リソースの実行時の読み込みをできるだけ効率的にします。 xcdatamodeldの「ソース」ディレクトリはmomdデプロイメントディレクトリにコンパイルされ、xcdatamodelの「ソース」ファイルはmomデプロイメントファイルにコンパイルされます。

momcは/ Developer/usr/bin /にあります。独自のビルドスクリプトで使用する場合、その使用法はmomcソース宛先です。ここで、ソースはコンパイルするCore Dataモデルのパスであり、宛先は出力のパスです。

「/ Developer/usr/bin /」とは、「/ Applications/Xcode.app/Developer/usr/bin /」を意味します

ターゲットスキームにスクリプトを追加して、各ビルドの前に(または重要ではないと考えてから)これを自動的にコンパイルできます。開発中にモデルを変更した場合に備えてください。

このようなもの:

mkdir -p "${BUILT_PRODUCTS_DIR}/your_model_name.momd"
momc "${SRCROOT}/your_model_path/your_model_name.xcdatamodeld" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/your_bundle_name.bundle/your_model_name.momd"
4
jackal

モデルリソースにはmainBundleからアクセスできなくなりました。次のようにbundleForClass:を使用する必要があります。

NSURL *modelURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"MyApp" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
2
Ric Santos

フレームワークにコアデータを含めようとする場合は、次のようにします。

yourFrameworkで-新しいファイル/コアデータ/データモデルを追加...-すべてのオブジェクトを作成...

YourFrameworkを使用する新しいプロジェクトを作成するときは、コアデータがオンになっていることを確認してください Use Core Data : On

これにより、AppDelegate内にすべてのボイラープレートが作成されます。

テストプロジェクトで-フレームワークを追加-フレームワークを埋め込みフレームワークとして追加-DELETE .xcdatamodeldファイル-AppDelegateで:

- (NSManagedObjectModel *)managedObjectModelメソッドを次のように変更します。

NSBundle * testBundle = [NSBundle bundleWithIdentifier:@"YourFramework bundle id "];

NSURL *modelURL = [testBundle URLForResource:@"Model" withExtension:@"momd"];

どこ YourFramework bundle idはYourFrameworkのバンドルIDです(一般/バンドルID)

ModelはYourFramework内の.xcdatamodeldファイルの名前です

これは機能します。

それが役に立てば幸い。

0
Marko Zadravec

データモデルのみが必要だと思います。

もしそうなら、私は一貫して、あるプロジェクトから別のプロジェクトにデータモデルファイル全体をコピーするための最も成功した方法を見つけます...

  1. ターゲットプロジェクトにある.xcdatamodeldファイルの現在のコピーをすべて削除します。
  2. Xcodeを閉じます。

    Finder(またはcmd行)を使用する。

  3. 元の.xcdatamodeldファイルを含むXcodeプロジェクトフォルダーを選択します。
  4. 元の.xcdatamodeldファイルのコピーを作成します。
  5. 元の.xcdatamodeldファイルのコピーをターゲットプロジェクトに移動します。

    その後...

  6. Xcodeを開きます。
  7. メニューコマンド「Add files to> your project <」を使用して、元の.xcdatamodeldファイルのコピーを見つけ、プロジェクトに追加します。
  8. Project Navigatorを使用して、元の.xcdatamodeldファイルの名前を変更します(必要な場合)。
  9. ターゲットプロジェクトを「ビルドして実行」します。

これは役に立ちますか?

0
andrewbuilder