web-dev-qa-db-ja.com

ストアを開くために使用されるモデルは、ストアを作成するために使用されるモデルと互換性がありません

Xcode 3.2でコアデータモデルを作成し、Xcode 4.2でアップグレードした後、NSManagedObjectサブクラスの新しいエンティティを追加しました(新しいエンティティを参照)。

まず、古いグループと同じグループに属していないため、奇妙に見えます。これが私のxcode 4.2の写真です(AlkitabDBはxcode 3.2で作成したもので、EndeDBは現在のxcodeバージョン(4.2)からの新しいものです:

the new entity do not grouped in xdatamodel

2番目に、そのままにして、最初のエンティティ(古いエンティティ)と同じ方法で2番目のエンティティ(新しいエンティティ)にアクセスすると、タイトルのエラーが表示されます。

エラーは次のとおりです。

2012-01-16 21:13:38.496 iHuria[55953:207] Unresolved error Error Domain=NSCocoaErrorDomain Code=134100 "The operation couldn’t be completed. (Cocoa error 134100.)" UserInfo=0x8829cd0 {metadata=<CFBasicHash 0x882a370 [0x1839b38]>{type = immutable dict, count = 7,
entries =>
    2 : <CFString 0x8829b90 [0x1839b38]>{contents = "NSStoreModelVersionIdentifiers"} = <CFArray 0x8829ff0 [0x1839b38]>{type = immutable, count = 0, values = ()}
    4 : <CFString 0x8829bc0 [0x1839b38]>{contents = "NSPersistenceFrameworkVersion"} = <CFNumber 0x8829770 [0x1839b38]>{value = +320, type = kCFNumberSInt64Type}
    6 : <CFString 0x8829bf0 [0x1839b38]>{contents = "NSStoreModelVersionHashes"} = <CFBasicHash 0x882a080 [0x1839b38]>{type = immutable dict, count = 1,
entries =>
    0 : <CFString 0x882a010 [0x1839b38]>{contents = "AlkitabDB"} = <CFData 0x882a030 [0x1839b38]>{length = 32, capacity = 32, bytes = 0xd02ac5f8be6ab0b39add450aca202ac0 ... 3d45d462998d2ccd}
}

    7 : <CFString 0x10e3aa8 [0x1839b38]>{contents = "NSStoreUUID"} = <CFString 0x8829e60 [0x1839b38]>{contents = "4F2EE7FF-463B-4055-BBED-8E603CDBDF59"}
    8 : <CFString 0x10e3948 [0x1839b38]>{contents = "NSStoreType"} = <CFString 0x10e3958 [0x1839b38]>{contents = "SQLite"}
    9 : <CFString 0x8829c40 [0x1839b38]>{contents = "NSStoreModelVersionHashesVersion"} = <CFNumber 0x6b1c7c0 [0x1839b38]>{value = +3, type = kCFNumberSInt32Type}
    10 : <CFString 0x8829c70 [0x1839b38]>{contents = "_NSAutoVacuumLevel"} = <CFString 0x882a0c0 [0x1839b38]>{contents = "2"}
}
, reason=The model used to open the store is incompatible with the one used to create the store}, {
    metadata =     {
        NSPersistenceFrameworkVersion = 320;
        NSStoreModelVersionHashes =         {
            AlkitabDB = <d02ac5f8 be6ab0b3 9add450a ca202ac0 ebd1e860 cbb578c2 3d45d462 998d2ccd>;
        };
        NSStoreModelVersionHashesVersion = 3;
        NSStoreModelVersionIdentifiers =         (
        );
        NSStoreType = SQLite;
        NSStoreUUID = "4F2EE7FF-463B-4055-BBED-8E603CDBDF59";
        "_NSAutoVacuumLevel" = 2;
    };
    reason = "The model used to open the store is incompatible with the one used to create the store";
}

以前に解決策を探しましたが、シミュレーターからアプリケーションを削除してアプリを再実行する必要があることがわかりましたが、機能しませんでした。誰もがこの問題の解決策を知っていますか?助けてください。

178
dejoong

シミュレーターからアプリを削除し、プロジェクトでクリーンを実行します。これにより、これらの問題が解決されます。アプリを削除するときにデバッガーで実行していないことを確認してください。そうしないと、アプリが実際に正しく削除されません。

確実に削除したい場合は、実行中のバージョンの下にあるアプリのフォルダーのUsers/INSERT_YOUR_USER_HERE/Library/Application Support/iPhone Simulator/ディレクトリを確認してください。

注:これは開発専用です。実稼働環境では、何らかの移行を実装する必要があります。 Googleの「コアデータ移行」。軽量の移行が最も簡単です。

283

アプリの削除はそうでない場合があります!提案、アプリは既に公開されています!データベースに新しいエンティティを追加して先に進むことはできません-移行を実行する必要があります!

ドキュメントを掘り下げたくなく、簡単な修正を探している人向け

  1. .xcdatamodeldファイルを開きます
  2. エディターをクリックします
  3. [モデルバージョンの追加...]を選択します。
  4. モデルの新しいバージョンを追加します(データモデルの新しいグループが追加されました)
  5. メインファイルを選択し、ファイルインスペクターを開きます(右側のパネル)
  6. Versioned core data modelの下で、現在のデータモデルのデータモデルの新しいバージョンを選択します
  7. それだけではありません)いわゆる「軽い移行」を実行する必要があります。
  8. AppDelegateに移動し、persistentStoreCoordinatorが作成されている場所を見つけます
  9. この行を見つけるif (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])
  10. nilオプションを@{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}に置き換えます(実際にそのメソッドのコメント化されたコードで提供されます)
  11. どうぞ、楽しんでください!

追伸これは、軽量移行にのみ適用されます。移行を軽量の移行として認定するには、変更を次の狭い帯域に限定する必要があります。

  • プロパティ(属性または関係)を追加または削除します。
  • オプションではないプロパティをオプションにします。
  • デフォルト値を指定する限り、オプション属性を非オプションにします。
  • エンティティを追加または削除します。
  • プロパティの名前を変更します。
  • エンティティの名前を変更します。

For Swift 4

coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true])
280
Stas

コアデータメソッドのAppDelegate.mファイルに次のようにpersistentStoreCoordinatorを作成するときにOptions属性を追加するだけです

目的C

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil)
    {
        return _persistentStoreCoordinator;
    }

    NSLog(@"persistentStoreCoordinator___");
    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"MyApp.sqlite"];

    NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
    [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
    [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
    {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    NSLog(@"persistentStoreCoordinator___2");
    return _persistentStoreCoordinator;
}

スイフト

    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
    // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
    // Create the coordinator and store
    let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
    let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
    var failureReason = "There was an error creating or loading the application's saved data."

    // MAIN LINE OF CODE TO ADD
    let mOptions = [NSMigratePersistentStoresAutomaticallyOption: true,
                    NSInferMappingModelAutomaticallyOption: true]

    do {
        try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: mOptions)
    } catch {
        // Report any error we got.
        var dict = [String: AnyObject]()
        dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
        dict[NSLocalizedFailureReasonErrorKey] = failureReason

        dict[NSUnderlyingErrorKey] = error as NSError
        let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
        // Replace this with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
        abort()
    }

    return coordinator
}

問題が解決しました。

32
Dhaval H. Nena

回答:シミュレーターからアプリを削除し、プロジェクトのクリーンと再ビルドを実行します。

注:コアデータの定義を変更するたびに、物理デバイスまたはシミュレーターにインストールされているアプリを削除し、プロジェクトをクリーンアップして、再ビルドします。

23
Bhavin

はい。物理デバイスでアプリを削除して再構築すると機能します。

14

Swiftの場合、AppDelegate.Swiftで次の行を見つけます。

try coordinator!.addPersistentStoreWithType(NSXMLStoreType, configuration:  nil, URL: url, options: nil )

そしてそれを

try coordinator!.addPersistentStoreWithType(NSXMLStoreType, configuration: nil, URL: url, options: [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true])
14

MergedModelFromBundlesのクラッシュと同様に、このエラーと戦い、「*という名前の2つの異なるエンティティを持つモデルをマージできません」というエラーを取得するのに数日費やしました。

根本的な問題は、Xcodeがデバイスから古いリソースを削除せず、競合を引き起こしていた古いバージョンのデータモデル(.momファイル)があったことでした。これが、アプリを削除するとデバイスの1つで問題が修正された理由です。

this blog post を別のSO回答で見つけた後、すべての.momファイルを検索する次の行を変更することで、古いモデルに対するアプリケーションの耐性を高めました。

NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];

これには、Filtersディレクトリのみを検索します。

NSString *path = [[NSBundle mainBundle] pathForResource:@"Filters" ofType:@"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];

thisからrecursivePathsForResourcesOfTypeを使用したので、question :アプリ内の.momファイル:

NSArray *momPaths = [self recursivePathsForResourcesOfType:@"mom" inDirectory:[[NSBundle mainBundle] resourcePath]];
NSLog(@"All .mom files:%@",momPaths);

また、 iExplorer を使用して、無関係な.momファイルを調べました(まだ削除しようとしませんでした)。

以下の方法も役立ちました。エンティティは、[psc managedObjectModel]によって返されたマージされたモデル内にあり、私のモデルまたはストア自体にはもう存在していなかったことを示しました。これは、古いモデルがデバイス自体にキャッシュされていて、きれいな建物が削除されなかったと信じさせたものです。メソッドは、同じ、変更、追加、またはモデルから削除された各エンティティをログに記録します。 ( this SO answer を開始点として記述):

- (BOOL)comparePersistentStore:(NSPersistentStoreCoordinator *)psc withStoreURL: (NSURL *)storeURL {
    NSError *error = nil;

    // Get the entities & keys from the persistent store coordinator
    NSManagedObjectModel *pscModel = [psc managedObjectModel];
    NSDictionary *pscEntities = [pscModel entitiesByName];
    NSSet *pscKeys = [NSSet setWithArray:[pscEntities allKeys]];
    //NSLog(@"psc model:%@", pscModel);
    //NSLog(@"psc keys:%@", pscKeys);
    NSLog(@"psc contains %d entities", [pscModel.entities count]);

    // Get the entity hashes from the storeURL
    NSDictionary *storeMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType
                                                                                          URL:storeURL
                                                                                        error:&error];
    NSDictionary *storeHashes = [storeMetadata objectForKey:@"NSStoreModelVersionHashes"];
    //NSLog(@"store metadata:%@", sourceMetadata);
    NSLog(@"store URL:%@", storeURL);
    NSLog(@"store NSStoreUUID:%@", [storeMetadata objectForKey:@"NSStoreUUID"]);
    NSLog(@"store NSStoreType:%@", [storeMetadata objectForKey:@"NSStoreType"]);
    NSSet *storeKeys = [NSSet setWithArray:[storeHashes allKeys]];

    // Determine store entities that were added, removed, and in common (to/with psc)
    NSMutableSet *addedEntities = [NSMutableSet setWithSet:pscKeys];
    NSMutableSet *removedEntities = [NSMutableSet setWithSet:storeKeys];
    NSMutableSet *commonEntities = [NSMutableSet setWithSet:pscKeys];
    NSMutableSet *changedEntities = [NSMutableSet new];
    [addedEntities minusSet:storeKeys];
    [removedEntities minusSet:pscKeys];
    [commonEntities minusSet:removedEntities];
    [commonEntities minusSet:addedEntities];

    // Determine entities that have changed (with different hashes)
    [commonEntities enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) {
        NSData *storeHash = [storeHashes objectForKey:key];
        NSEntityDescription *pscDescrip = [pscEntities objectForKey:key];
        if ( ! [pscDescrip.versionHash isEqualToData:storeHash]) {
            if (storeHash != nil && pscDescrip.versionHash != nil) {
                [changedEntities addObject:key];
            }
        }
    }];

    // Remove changed entities from common list
    [commonEntities minusSet:changedEntities];

    if ([commonEntities count] > 0) {
        NSLog(@"Common entities:");
        [commonEntities enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) {
            NSData *storeHash = [storeHashes objectForKey:key];
            NSEntityDescription *pscDescrip = [pscEntities objectForKey:key];
            NSLog(@"\t%@:\t%@", key, pscDescrip.versionHash);
        }];
    }
    if ([changedEntities count] > 0) {
        NSLog(@"Changed entities:");
        [changedEntities enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) {
            NSData *storeHash = [storeHashes objectForKey:key];
            NSEntityDescription *pscDescrip = [pscEntities objectForKey:key];
            NSLog(@"\tpsc   %@:\t%@", key, pscDescrip.versionHash);
            NSLog(@"\tstore %@:\t%@", key, storeHash);
    }];
    }
    if ([addedEntities count] > 0) {
        NSLog(@"Added entities to psc model (not in store):");
        [addedEntities enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) {
            NSEntityDescription *pscDescrip = [pscEntities objectForKey:key];
            NSLog(@"\t%@:\t%@", key, pscDescrip.versionHash);
        }];
    }
    if ([removedEntities count] > 0) {
        NSLog(@"Removed entities from psc model (exist in store):");
        [removedEntities enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) {
            NSData *storeHash = [storeHashes objectForKey:key];
            NSLog(@"\t%@:\t%@", key, storeHash);
        }];
    }

    BOOL pscCompatibile = [pscModel isConfiguration:nil     compatibleWithStoreMetadata:storeMetadata];
    NSLog(@"Migration needed? %@", [email protected]"no":@"yes");

    return pscCompatibile;
}

使用法:各ストアをNSPersistentStoreCoordinatorに追加する前に呼び出されます:

    [self comparePersistentStore:self.psc withStoreURL:self.iCloudStoreURL];
    _iCloudStore = [self.psc addPersistentStoreWithType:NSSQLiteStoreType
                                          configuration:nil
                                                    URL:self.iCloudStoreURL
                                                options:options
                                                  error:&localError];
11
Symmetric

Core Dateの定義を変更するたびに、物理デバイスまたはシミュレーターにインストールされているアプリを削除する必要があります。

10
pierrotlefou
  1. アプリの実行を停止します。
  2. シミュレーターでアプリを削除します。
  3. Product-> Clean
  4. ビルド、実行。
9
Tom Howard

Swift 2.1、Xcode 7で機能した最も簡単なソリューションは次のとおりです。

  1. シミュレーターからアプリを削除します(Cmd + Shift + Hでホーム画面に移動します。アプリを長押しし、十字をクリックします。通常の方法でスマートフォンからアプリを削除します)

  2. Cmd + Shift + Hをもう一度押して、アプリのダンスを停止します

  3. プロジェクトに戻って再実行します

2つのエンティティが設定されたCore Dataの書き込み/読み取り中にこの問題が発生しました。アプリを削除してプログラムを再実行すると、問題が修正されました

7
Naishta

Swiftを使用している場合。

@Stasの回答に従い、App Delegateでnilの代わりにオプションを挿入します。

let myOptions = [NSMigratePersistentStoresAutomaticallyOption: true,
            NSInferMappingModelAutomaticallyOption: true]
        if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: myOptions, error: &error) == nil {
6
JZ.

エンティティに変更を加えた後、[Simulator App Folder]/Document/*.sqliteファイルを削除しただけで機能しました。そしてもちろん、.sqliteファイルには、失われるすべての保存データと構造が含まれています。

6
AHHP

シミュレーターからアプリケーションを削除し、コードをクリーンアップして、.itsが正常に動作するようにしてください。

6
sarit bahuguna

シミュレーターで「コンテンツと設定のリセット」を試してください。アプリとクリーンビルドを削除した後、私のために働いた

5
Josh10

アプリで同じ問題が発生しました(App Storeでまだリリースされていません)。

修正方法は次のとおりです。

  1. クリーンを実行(Cmd + Shift + K)
  2. IOSシミュレーターを再起動します
  3. iOSシミュレーター->コンテンツと設定のリセット(navbarから)

(3)ようやく正常に動作するようになったステップでした。お役に立てれば!

4
bigtex777

Core Dataモデルに変更を加える場合、既存の永続オブジェクト(ユーザーが現在リリースされているバージョンで作成したもの)を新しいモデルに採用する方法をCore Dataに伝える移行ポリシーを提供する必要があります。

一部のシナリオでは、Core Dataは古いモデルから新しいモデルへのマッピングを自動的に推測できます。より複雑な変更については、移行を実行するロジックを実装する必要があります。

詳細は Core Data Model Versioning and Data Migration Programming Guide にあります。

更新
ここでのスタックオーバーフローに関する回答 は、Core Dataの軽量な移行の基本をカバーし、開始するためのコードも用意しています。

2

管理対象オブジェクトモデルのスキーマを変更するときに、デバイスからアプリを削除することもできますが、一部のシナリオではこれが不可能です。古いスキーマでアプリを既に公開しているためです。

この場合、古いデータを新しいスキーマに移行する必要があります。

コアデータモデルのバージョン管理とデータ移行

2
Mike

移行を使用してコアデータモデルを移行する必要があります。モデルを変更するときはいつでも、バージョン管理なしで非互換にします。自分を縛り付けてください、それは少し毛深い話題です。

http://developer.Apple.com/library/ios/#documentation/cocoa/Conceptual/CoreDataVersioning/Articles/Introduction.html

2
nevan king

最初に、xcdatamodeldバンドルに含める必要があるのは、xcdatamodelファイルのみです。サブクラスはではなくxcdatamodeldにある必要があります。それらを外に移動します。コンパイラを混乱させる可能性がかなりあります。

第二に、エラーはCore Dataがモデルを見つけられないことを示します。データを作成してからモデルに触れましたか?その場合、矛盾した状態にあり、データを削除するか(Philippeが提案した)、モデルの変更をロールバックすることで修正する必要がありますBACK

1
Marcus S. Zarra

この問題は通常、DBがインストールされているバージョン間の非互換性が作成されているために発生します。この問題に対する一般的なアプローチは、アプリを削除して再インストール itです。しかし、あなたの言及したケースでは、DBのバージョンはXcode 3.2と4.2で完全に異なります。したがって、同じバージョンのXcode for DBを使用することをお勧めします。

1

この問題が発生しました-最初にシミュレータをリセットしてから、プロジェクトをクリーンアップして再構築しました。そして、それは動作します。

0
Yashu

コアデータを変更する場合(テーブルへのフィールドの追加、フィールドの削除など)、アプリケーションドキュメントフォルダー内のsqliteファイルはスキーマと同期する必要があります。

このファイルはデフォルトでは上書きされません。このファイルを再生成する必要があります。

次の手順を実行します:

  1. NSURLが指すフォルダーに移動します。 (このパスは、クラッシュする前にアプリケーションによって生成された例外メッセージにあります。)例:/ Users // Library/Application Support/iPhone Simulator // Applications // Documents

  2. sqliteファイルを削除または名前変更します

  3. アプリケーションをクリーンアップして再実行する
  4. アプリケーションを再実行すると、新しいsqliteファイルが生成されます。

これにより、スキーマとXcodeが同期していることが確認されます。

0

エラーが発生していましたが、エラーが発生した理由は次のとおりです。

もともと「エントリ」という名前のエンティティが1つあり、そのエンティティに対してデータベースに1つの行が保存されていました。次に、「Person」という名前の別のエンティティを追加しましたが、追加した後、ビルドに進み、エラーが発生しました。そこで、「Person」エンティティを削除してからアプリを構築し、「Entry」にある行を削除してからアプリケーションを閉じることで問題を解決しました。その後、携帯電話からアプリを完全に削除し、再構築を行ったところ問題なく機能しました。どのステップで問題(行またはアプリの削除)が修正されたかはわかりませんが、うまくいけば、解決策を探している場合に役立つでしょう。 :)

編集:ああ、アプリを再度ビルドするために新しいエンティティ(私の場合は "Person")を削除することを心配した場合は、後でCMD + Zを使用して元に戻すことができます。

0
daveomcd