11

背景

  • 2つの管理対象オブジェクトモデルを備えたCocoa非ドキュメントコアデータプロジェクト。
  • モデル1は同じままです。モデル2が変更されたので、ストアを移行したいと思います。
  • Xcodeで[デザイン]>[データモデル]>[モデルバージョンの追加]で新しいバージョンを作成しました。
  • バージョン間の違いは、1対多に変更された単一の関係です。
  • モデルに変更を加えて保存しました。
  • 古いモデルをソースとして、新しいモデルを宛先として持つ新しいマッピングモデルを作成しました。
  • すべてのマッピングモデルとデータモデルがコンパイルされ、すべてがアプリバンドルのリソースフォルダーにコピーされていることを確認しました。
  • 永続ストアを追加するときのように、NSMigratePersistentStoresAutomaticallyOption キーを使用して辞書を渡すことにより、移行をオンにしました 。[NSNumber numberWithBool:YES]
  • バンドル内のすべてのモデルをマージするのではなく、使用する2つのモデル(モデル1とモデル2の新しいバージョン)を指定し、を使用してそれらをマージしました。modelByMergingModels:

問題

移行するために何をしても、次のエラーメッセージが表示されます。

「永続的なストアの移行に失敗しました。ソース管理対象オブジェクトモデルがありません。」

私が試したこと

  • ビルドするたびにクリーンアップします。
  • リソースに移行先のモデルのみを含めるか、コンパイルするか、またはその両方を行うさまざまな組み合わせを試しました。
  • エラーメッセージは、移行用のソースモデルが見つからないことを示しているため、Resourcesフォルダーとコンパイルの両方にモデルのすべてのバージョンを入れてみました。
  • データモデルの元のバージョンに戻すことで、本当に基本的なエラーが発生していないことを確認しました。アプリは正常に動作します。
  • マッピングモデルとモデルの新しいバージョンを削除し、クリーンアップしてから、両方を再作成しました。
  • 新しいモデルに別の変更を加えてみました-代わりにエンティティを削除します。

私は私の知恵の終わりにいます。

どこかで見たことのない大きな間違いを犯したと思わずにはいられません。何か案は?

4

6 に答える 6

16

2つの可能性:

  1. アプリのソースモデルは、ディスク上の実際のストアと一致しません。
  2. マッピングモデルがソースモデルと一致しません。

Core Dataのデバッグをオンにすると、CoreDataが移行を実行しているときに探しているハッシュを確認できるはずです。これらのハッシュをディスク上のストアにあるものと比較し、それらが一致するかどうかを確認します。同様に、デバッグにより、マッピングモデルのハッシュを確認して、すべてを一致させることができます。

位置がずれているのがマッピングモデルだけの場合は、Xcodeのデザインメニューからソースから更新するように指示できます。ディスク上のストアファイルの実際のソースモデルが欠落している場合は、バージョン管理システムを調べるか、自動移行を使用して、そのファイルをソースであると思われるモデルに移行してみてください。

アップデート1

ソースモデルとデスティネーションモデルを変更する場所が、エディターウィンドウの下部に移動しました。

于 2010-03-22T12:37:23.653 に答える
6

バンドル内のすべてのモデルをマージするのではなく、使用する2つのモデル(モデル1とモデル2の新しいバージョン)を指定し、modelByMergingModelsを使用してそれらをマージしました。

これは正しくないようです。なぜモデルをマージするのですか?モデル2を使用し、モデル1からストアを移行します。

NSManagedObjectModelクラスリファレンスから

modelByMergingModels:

既存のモデルの配列から単一のモデルを作成します。

ソースモデル(モデル1 )で特別なことや特定のことを行う必要はありません。バンドルに含まれている限り、自動軽量移行プロセスがそれを検出して使用します。

自動軽量移行と比較してひどいパフォーマンスが見られたので、Xcodeで作成したマッピングモデルを放棄することをお勧めします。あなたのマイレージは変わるかもしれません、モデル間の私の変化はあなたのものとは異なります、しかし私は驚かないでしょう。バンドルに独自のマッピングモデルがある場合とない場合で、タイミングを試してください。

 /* Inferred mapping */
 NSError *error;
 NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                          [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                          [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,nil];
 NSPersistentStore *migratedStore = [persistentStoreCoordinator addPersistentStoreWithType:nil
                                                                             configuration:nil
                                                                                       URL:self.storeURL
                                                                                   options:options
                                                                                     error:&error];
 migrationWasSuccessful = (migratedStore != nil);

ソースモデルをロードしてnilでないことを確認することで、コードでソースモデルが使用可能であることを確認できます。

NSString *modelDirectoryPath = [[NSBundle mainBundle] pathForResource:@"YourModelName" ofType:@"momd"];
if (modelDirectoryPath == nil) return nil;
NSString *modelPath = [modelDirectoryPath stringByAppendingPathComponent:@"YourModelName"];
NSURL *modelFileURL = [NSURL fileURLWithPath:modelPath];
NSManagedObjectModel *modelOne = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelFileURL];
if (modelOne == nil) {
    NSLog(@"Woops, Xcode lost my source model");
}
else {
    [modelOne release];
}

これは、プロジェクトにリソース「YourModelName.xcdatamodeld」と「YourModelName.xcdatamodel」があることを前提としています。


また、そのモデルが既存の移行前の永続ストアと互換性があるかどうかを確認できます。

NSError *error;
NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:self.storeURL error:&error];
if (storeMeta == nil) {
    // Unable to read store meta
    return NO;
}
BOOL isCompatible = [modelOne isConfiguration:nil compatibleWithStoreMetadata:storeMeta];

-storeURLこのコードは、永続ストアのロード元を指定するメソッドがあることを前提としています。

于 2010-04-01T05:01:25.947 に答える
4

このエラーが発生したとき、コアデータモデルを更新しましたが、テスト用電話からアプリインスタンスをクリアしていませんでした。これは、電話のコアデータに保存されたモデルが、コードで使用しようとしていたものと一致しなかったことを意味します。

私は電話からアプリを削除し、正常に再構築/実行しました。

于 2019-02-06T17:50:09.260 に答える
3

既存のアプリのコアデータモデルをアップグレード(およびレガシーデータを移行)しようとしているときに、サードパーティのフレームワークがアプリのデータベースにデータを書き込んでいるシナリオに遭遇しました。「ソースストアのモデルが見つかりません」というエラーが発生していました。移行を試みたときにサードパーティモデルがロードされなかったため、移行が失敗していました。

この問題のトラブルシューティング中に、このメソッド(以下)を作成しました。この種の問題に直面している人には役立つかもしれません。

- (BOOL) checkModelCompatibilityOfStoreWithURL: (NSURL *) myStoreURL
                                 forModelNamed: (NSString *) myModelName
                                  withBasePath: (NSString *) myBasePath;
{
    NSError * error = nil;
    NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:myStoreURL error:&error];
    if (!storeMeta) {
        NSLog(@"Unable to load store metadata from URL: %@; Error = %@", myStoreURL, error);
        return NO;
    }

    NSString * modelPath = [myBasePath stringByAppendingPathComponent: myModelName];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if (![fileManager fileExistsAtPath: modelPath]) {
        // uh oh
        NSLog(@"Can't find model.");
        return NO;
    }

    NSURL * modelURL = [NSURL fileURLWithPath: modelPath];
    NSManagedObjectModel * model = [[[NSManagedObjectModel alloc] initWithContentsOfURL: modelURL] autorelease];
    BOOL result = [model isConfiguration: nil compatibleWithStoreMetadata: storeMeta];

    NSLog(@"Tested model, %@, is%@ compatible with Database", modelPath, result ? @"" : @" ~not~");

    return result;
}

このコードスニペットは、ストアのメタデータを取得します。

NSError *error = nil;
NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:storeUrl error:&error];
NSLog(@"%@", [storeMeta objectForKey: @"NSStoreModelVersionHashes"]);

VersionInfo.plist(コンパイルされたアプリのバンドルに格納されている)には、モデル内のさまざまなエンティティ(base64エンコーディング)に関連付けられているハッシュが含まれています。同様に、データストア(Z_METADATA.Z_PLIST)のBLOB列には、データに関連付けられている各エンティティのハッシュ(base64エンコード)を含むバイナリエンコードのプロパティリストが含まれています。

NSManagedObjectModelの-entitiesByNameメソッドは、特定のモデル内に存在するエンティティとハッシュをダンプするのに役立ちます。

于 2011-06-02T20:56:51.783 に答える
1

私も同様の問題を抱えていました。を使用+modelByMergeingModels:しましたが、マッピングモデルを使用しませんでした。ただし、モデルのマージは軽量データ移行では機能しません。

Apple Docsから:

自動軽量移行を実行するには、 CoreDataが実行時にソースおよび宛先の管理対象オブジェクトモデル自体を検出できる必要があります。

それよりも使用する場合+modelByMergeingModels:は、宛先モデルに使用されます。ただし、CoreDataはソースモデルを見つけることができません。ソースモデルは+modelByMergeingModels:古いバージョンのアプリケーションを使用して作成されており、CoreDataはモデルをマージしてソースモデルを見つけようとします。

私がやったことは.xcdatamodeld、モデルのXMLファイルを編集して(手動で)新しいマージを作成し、それをプロジェクトに追加し、コンパイルソースから個別のを削除し、のURLでuseを使用する.xcdatamodeld代わりにしたことです。新しいマージされたモデル。将来、モデルを自動的にマージするスクリプトを作成する可能性があります。+modelByMergeingModels:NSManagedObjectModel-initWithContentsOfURL:

于 2014-11-20T17:52:54.530 に答える
1

Mac Catalystアプリケーションでこの問題が発生した場合は、〜/ Library / Containers/name-of-appにある保存データを削除する必要があります。

于 2021-08-18T08:15:01.493 に答える