iphone - 用於打開商店的模型與用於創建商店的模型不兼容




core-data xcode4 (21)

每次更改Core Time定義時,都應該刪除安裝在物理設備或模擬器上的應用程序。

我在xcode 3.2中創建了一個Core Data模型,然後在Xcode 4.2中升級之後,我添加了一個NSManagedObject子類的新實體(參考新實體)。

首先,它看起來很奇怪,因為它與舊的不在同一個組中。 這是我的xcode 4.2上的圖片(AlkitabDB是我在xcode 3.2中創建的,EndeDB是當前xcode版本(4.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";
}

我之前查找了解決方案,發現我應該從模擬器中刪除應用程序,然後重新運行應用程序,但它不起作用。 有沒有人知道這個問題的解決方案? 請幫忙。


由於在其上創建了數據庫的版本之間不兼容,通常會發生此問題。 解決這個問題的一般方法是刪除應用程序並重新安裝 。 但在你提到的情況下,在Xcode 3.2和4.2上DB的版本完全不同。 所以最好使用相同版本的Xcode for DB。


我遇到了與我的應用程序相同的問題(尚未在App Store中發布)。

以下是我如何修復它:

  1. 運行清理(Cmd + Shift + K)
  2. 重新啟動iOS模擬器
  3. iOS模擬器 - >重置內容和設置(從導航欄)

(3)是最終讓它正常運行的步驟。 希望這可以幫助!



iOS模擬器 - >重置內容和設置...

為我工作

iOS模擬器 - >重置內容和設置... - >在iOS9(xcode 7.1)上重置也可以


在Swift 2.1,Xcode 7中為我工作的最簡單的解決方案是:

  1. 從模擬器中刪除應用程序(Cmd + Shift + H進入主屏幕。長按應用程序,點擊交叉,就像通常的從手機中刪除應用程序的方式)

  2. Cmd + Shift + H再次停止應用程序的跳舞

  3. 回到你的項目並重新運行

我在設置2個實體的情況下從Core Data寫入/讀取時遇到此問題。 刪除應用程序並重新運行程序解決了問題


我得到的錯誤,但我得到錯誤的原因是因為以下。

我最初有一個名為“Entry”的實體,並且在數據庫中為該實體保存了一行。 然後我添加了另一個名為“Person”的實體,並在添加之後去構建並得到錯誤。 因此,我通過刪除“Person”實體,然後構建應用程序,刪除“Entry”中的行,然後關閉應用程序來解決該問題。 然後,我完全從手機中刪除了該應用程序,然後重建並運行正常。 不知道哪一步糾正了問題(刪除行或應用程序),但希望如果您正在尋找解決方案,這將有所幫助。 :)

編輯:哦,如果你擔心刪除你的新實體(在我的情況下“人”)再次構建應用程序,記住你可以通過使用CMD + Z來取回它!


請從模擬器中刪除一個應用程序並清理一個代碼並運行。它可以正常工作。它可能是它的幫助。


嘗試模擬器中的“重置內容和設置”。 刪除應用程序和清理版本後為我工作


我有這個問題 - 我首先重置我的模擬器,然後清理項目並重建。 然後它工作。


如果您對核心數據模型進行了更改,則必須提供一個遷移策略,告訴Core Data如何將現有的持久對象(您的用戶使用當前發布的版本創建)應用於新模型。

對於某些情況,核心數據能夠自動推斷從舊模型到新模型的映射。 對於更複雜的更改,您可能必須執行一些執行遷移的邏輯。

詳細信息可以在developer.apple.com/library/ios/#documentation/cocoa/Conceptual/…

更新
的這個答案涵蓋了Core Data輕量級遷移的基礎知識,並且還有一些代碼可以幫助您入門。


  1. 停止運行應用程序。
  2. 在模擬器上刪除應用程序。
  3. Product - > Clean
  4. 建立,運行。

如果你正在使用Swift。

按照@Stas的回答,在您的App Delegate中插入選項,代替nil:

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

我只是花了好幾天的時間來解決這個錯誤,以及mergedModelFromBundles崩潰,並且得到了“不能合併具有兩個不同實體名稱*”錯誤的模型。

事實證明,根本問題在於Xcode不會從設備中刪除舊資源,而且我的舊版本數據模型(.mom文件)會導致衝突。 這就是為什麼刪除應用程序可以解決我的某個設備上的問題。

通過另一個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];

我從這個問題中使用了recursivePathsForResourcesOfType :通過在應用程序中記錄所有的.mom文件來幫助解決這個問題

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

我還使用iExplorer查看無關的.mom文件(我沒有嘗試刪除它們)。

下面的方法也很有幫助。 它表明一個實體處於由[psc managedObjectModel]返回的合併模型中,該模型在我的任何模型或商店本身中都不再存在。 這讓我相信一個舊的模型被緩存在設備本身上,那個乾淨的建築並沒有被移除。 該方法記錄每個相同,已更改或添加或刪除模型的實體。 (用這個SO回答作為起點):

- (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];

從模擬器中刪除應用程序並執行清理項目。 這應該解決這些問題。 確保在刪除應用程序時沒有在調試器中運行,否則它不會正確刪除它。

如果你想確定它已經不存在了,請在你正在運行的版本下檢查這個目錄Users/INSERT_YOUR_USER_HERE/Library/Application Support/iPhone Simulator/用於你的應用程序的文件夾。

注意:這僅用於開發。 為了生產,你需要實施某種遷移。 谷歌的“核心數據遷移”,輕量級遷移是最簡單的。


對於mac應用程序開發:

  1. 清理項目
  2. 清理派生數據
  3. 進入/ Users / YOUR_NAME / Library / Containers / YOUR_APP_BUNDLE_ID / Data / Documents /並刪除裡面的所有文件(例如“.sqlite”,“.sqlite-shm”...)

它為我工作,希望這可能會有所幫助。


首先,應該在xcdatamodeld包中唯一的東西是xcdatamodel文件。 你的子類應該在xcdatamodeld 。 把他們移出去。 他們混淆編譯器的可能性很大。

其次,錯誤表明核心數據找不到您的模型。 您是否創建了數據,然後觸摸了模型? 如果是這樣,你處於不一致的狀態,需要通過刪除數據(Philippe建議的)或通過滾動模型BACK的更改來修復該問題。


如下所示,在AppDelegate.m文件中為核心數據方法創建persistentStoreCoordinator時,只需添加選項屬性

Objective-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
}

它解決了我的問題..


答案:從模擬器中刪除應用程序,執行清理並重新構建您的項目。

注意:只要您對Core Data定義進行更改,刪除安裝在物理設備或模擬器上的應用程序,請再次清理項目並重新構建。


在對實體進行更改後,我剛剛刪除了[Simulator App Folder]/Document/*.sqlite文件,並且它工作正常。 當然,.sqlite文件包含將丟失的所有存儲數據和結構。


我相信Ryan是在正確的道路上:當一個項目有1,500個文件(我決定測試的數量)時,產生的線程太多了。

所以,我重構上面的代碼就像這樣工作:

- (void) establishImportLinksForFilesInProject:(LPProject *)aProject
{
        dispatch_queue_t taskQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

     dispatch_async(taskQ, 
     ^{

     // Create a new Core Data Context on this thread using the same persistent data store    
     // as the main thread. Pass the objectID of aProject to access the managedObject
     // for that project on this thread's context:

     NSManagedObjectID *projectID = [aProject objectID];

     for (LPFile *fileToCheck in [backgroundContext objectWithID:projectID] memberFiles])
     {
        if (//Some condition is met)
        {
                // Here, we do the scanning for @import statements. 
                // When we find a valid one, we put the whole path to the 
                // imported file into an array called 'verifiedImports'. 

                // Pass this ID to main thread in dispatch call below to access the same
                // file in the main thread's context
                NSManagedObjectID *fileID = [fileToCheck objectID];


                // go back to the main thread and update the model 
                // (Core Data is not thread-safe.)
                dispatch_async(dispatch_get_main_queue(), 
                ^{
                    for (NSString *import in verifiedImports)
                    {  
                       LPFile *targetFile = [mainContext objectWithID:fileID];
                       // Add the relationship to targetFile. 
                    }
                 });//end block
         }
    }
    // Easy way to tell when we're done processing all files.
    // Could add a dispatch_async(main_queue) call here to do something like UI updates, etc

    });//end block
    }

所以,基本上,我們現在正在生成一個讀取所有文件而不是每個文件一個線程的線程。 此外,事實證明在main_queue上調用dispatch_async()是正確的方法:工作線程將該塊分派給主線程,並且在繼續掃描下一個文件之前不等待它返回。

這個實現基本上建立了一個“串行”隊列,正如Ryan建議的那樣(for循環是它的串行部分),但有一個優點:當for循環結束時,我們已經完成了處理所有文件,我們可以堅持dispatch_async(main_queue)阻止那裡做我們想做的事。 這是一種非常好的方式來判斷並發處理任務何時完成且舊版本中不存在。

這裡的缺點是在多線程上使用Core Data會有點複雜。 但對於擁有5,000個文件的項目(這是我測試過的最高級別),這種方法似乎是無懈可擊的。





iphone core-data xcode4