【问题标题】:iPhone Core Data Lightweight Migration Cocoa error 134130: Can't find model for source storeiPhone Core Data Lightweight Migration Cocoa 错误 134130:找不到源存储的模型
【发布时间】:2010-06-30 04:41:18
【问题描述】:

伙计们,

轻量级迁移在这条线上 100% 的时间都失败了:

[persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]

出现错误:

Error: Error Domain=NSCocoaErrorDomain Code=134130 UserInfo=0x4fbff20 "Operation could not be completed. (Cocoa error 134130.)"
"Can't find model for source store";

这是我的托管对象上下文、模型和持久存储:

- (NSManagedObjectContext *) managedObjectContext {

    if (managedObjectContext != nil) {
        return managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        managedObjectContext = [[NSManagedObjectContext alloc] init];
        [managedObjectContext setPersistentStoreCoordinator: coordinator];
    }
    return managedObjectContext;
}

- (NSManagedObjectModel *)managedObjectModel {

    if (managedObjectModel != nil) {
        return managedObjectModel;
    }

    managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    
    return managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }

    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"Locations.sqlite"]];

    NSError *error;
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];

    // Allow inferred migration from the original version of the application.
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
        NSLog(@"Error: %@",error);
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }    

    return persistentStoreCoordinator;
}

我的项目中有两个版本的模型:一个版本 4 和一个版本 5。如果我将版本 4 设置为默认值,它可以正常工作。如果我选择“设计 -> 数据模型 -> 添加模型版本”(如this post 所述),进行更改,设计 -> 数据模型 -> 设置当前版本,构建并运行,它将失败并出现上述“找不到源存储的模型”错误。将模型设置回版本 4,没有问题,添加 PersistentStoreWithType。或者,如果我添加模型版本并且不进行任何更改,只需从版本 4 转到 5 而不添加任何新字段,没有问题。如果我再尝试从 5 到 6,就会出现上述错误。

此代码在模拟器和手机上均失败。我读了几个要求删除和重新安装应用程序的处方,这对模拟器和手机都有效,但我担心当我将它发布给真实用户时,它会破坏我的安装基础,因为他们将无法删除和重新安装- App Store 将自动升级它们。

此代码在过去的版本中有效,我没有进行任何更改 - 因此我能够将其一直升级到版本 4。我最近升级到 iOS4 的 XCode 3.2.3 构建,这可能与此有关.

现在有没有人和我一样突然遇到这个问题?有没有人设法克服它?谢谢。

PS - 对于偶然发现此页面的 Google 员工,以下是您可能考虑阅读的所有相关页面。不幸的是,这些都没有解决我的问题。

更新

虽然这不是真正的修复,但它确实避免了客户端崩溃的情况:只需删除数据库文件:

if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {



    // Delete file
    if ([[NSFileManager defaultManager] fileExistsAtPath:storeUrl.path]) {
        if (![[NSFileManager defaultManager] removeItemAtPath:storeUrl.path error:&error]) {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        } 
    }

    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) 
    {
        // Handle the error.
        NSLog(@"Error: %@",error);
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();

    }
}    

更新 2

当我检查 VersionInfo.plist 时会发生以下情况:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>NSManagedObjectModel_CurrentVersionName</key>
        <string>Profile 5</string>
        <key>NSManagedObjectModel_VersionHashes</key>
        <dict>
                <key>Profile</key>
                <dict>
                        <key>Profile</key>
                        <data>
                        ZIICGgMBreuldkPXgXUhJwKamgwJzESM5FRTOUskomw=
                        </data>
                </dict>
                <key>Profile 2</key>
                <dict>
                        <key>Profile</key>
                        <data>
                        tEB7HrETWOSUuoeDonJKLXzsxixv8ALHOoASQDUIZMA=
                        </data>
                </dict>
                <key>Profile 3</key>
                <dict>
                        <key>Profile</key>
                        <data>
                        qyXOJyKkfQ8hdt9gcdFs7SxKmZ1JYrsXvKbtFQTTna8=
                        </data>
                </dict>
                <key>Profile 4</key>
                <dict>
                        <key>Profile</key>
                        <data>
                        lyWDJJ0kGcs/pUOModd3Q1ymDvdRiNXui4NCpLxDFSw=
                        </data>
                </dict>
                <key>Profile 5</key>
                <dict>
                        <key>Profile</key>
                        <data>
                        V4PyRK1ezj3xK1QFRCTVzGOqyJhEb7FRMzglrTsP0cI=
                        </data>
                </dict>
        </dict>
</dict>
</plist>

这是我为检查模型而编写的代码(请注意,我必须添加一个 base64 编码器,因为这就是 VersionInfo.plist 文件中的内容)

if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {


    NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:storeUrl error:&error];
    NSLog(@"%@",storeMeta);
    id someObj = [[storeMeta objectForKey:@"NSStoreModelVersionHashes"] objectForKey:@"Profile"];
    NSLog(@"%@",someObj);
    NSLog(@"%@",[NSString base64StringFromData:someObj length:[someObj length]]);

这是调试输出:

{
    NSPersistenceFrameworkVersion = 310;
    NSStoreModelVersionHashes =     {
        Profile = <97258324 9d2419cb 3fa5438c a1d77743 5ca60ef7 5188d5ee 8b8342a4 bc43152c>;
        SerializedMessage = <4530863c d943479a edfb4dfb 5059c28d d6137dc4 d1153d36 ed52be49 11074f13>;
    };
    NSStoreModelVersionHashesVersion = 3;
    NSStoreModelVersionIdentifiers =     (
    );
    NSStoreType = SQLite;
    NSStoreUUID = "823FD306-696F-4A0F-8311-2792825DC66E";
    "_NSAutoVacuumLevel" = 2;
}

<97258324 9d2419cb 3fa5438c a1d77743 5ca60ef7 5188d5ee 8b8342a4 bc43152c>
lyWDJJ0kGcs/pUOModd3Q1ymDvdRiNXui4NCpLxDFSw=

如您所见,以“ly”开头的最后一行与 VersionInfo.plist 中的配置文件 4 匹配......因此我看不出它应该失败的原因。还有其他想法吗?

【问题讨论】:

    标签: iphone core-data


    【解决方案1】:

    我读了几个处方 用于删除和重新安装应用程序, 这对模拟器和 电话,但我害怕当我 将此发布给真实用户 打破我的安装基础,因为他们 将无法删除并重新安装。

    这是由于 Xcode 在更改模型文件(例如更改名称。旧文件仍然存在,导致混乱。这是你只能在开发过程中看到的东西,因为它是 Xcode 操作应用程序包的方式的产物,而无需每次都完全重新安装它,而发布版本必须这样做。

    您可以确认此记录返回:

    [[NSBundle mainBundle] URLsForResourcesWithExtension:@"momc"subdirectory:nil];
    

    ...这应该会显示应用程序包中所有已编译的模型文件

    在开发过程中依赖迁移是不好的做法,因为如果您对模型和存储进行更改,迁移失败是很常见的。您应该只在确定所有代码后使用迁移。我还建议您每次运行时都从头开始重新生成商店。通过改变模型很容易在商店中建立垃圾。

    【讨论】:

    • 我能够通过使用 Testflightapp.com(即将 RIP)制作我的应用程序的“发布”版本来确认这对我有用,我能够将其加载到具有先前版本的测试设备上应用程序的版本。它安装并运行良好,我能够从手机上下载数据库并确认它已成功迁移,这就是我不想删除应用程序并通过 Xcode 重新安装的全部意义——想确认迁移可以工作,因为我使用的是 MagicalRecord 3 并且必须修改一些 MR 代码,因为我的默认“堆栈”不支持迁移 OOTB。
    【解决方案2】:

    我已阅读您更新的问题。模型版本变得非常混乱。

    您应该尝试审核现有商店实际要求的模型版本,并尝试在运行时列出应用程序包中的所有可用模型。


    我查看我的应用的模型目录

    NSString *modelDirectoryPath = [[NSBundle mainBundle] pathForResource:@"MyModel" ofType:@"momd"];
    

    我不确定开发人员是否通常会这样做,但我将我的模型版本保留了不同的名称......所以我在那里:

    • VersionInfo.plist
    • MyModel.mom
    • MyModel2.mom

    VersionInfo.plist 中列出的版本哈希应该可以帮助您进行故障排除。查找现有持久存储所需的版本哈希,看看是否可以在VersionInfo.plist 中列出的版本哈希中找到它。

    实际上,我无法编写一些代码来询问持久存储它的实体版本哈希值是什么。 NSPersistentStoreCoordinatorNSMigrationManger 似乎是私下做的。即,他们根据存储加载的模型检查持久存储实体版本。


    又快速浏览了一下,它在商店元数据中可用。又好又简单!

    NSError *error;
    NSURL *storeURL = [NSURL fileURLWithPath:[[self class] storePath]];
    NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:storeURL error:&error];
    

    查看storeMeta 我得到了一把钥匙

    <CFString 0x7328050 [0x2724380]>{contents = "NSStoreModelVersionHashes"} = <CFBasicHash 0x7328340 [0x2724380]>{type = immutable dict, count = 5,
    entries =>
        0 : <CFString 0x7328110 [0x2724380]>{contents = "MyEntityNameOne"} = <CFData 0x73281b0 [0x2724380]>{length = 32, capacity = 32, bytes = 0x143325cf121239ce156af2e2a1aad7d9 ... 976977fdf29fc013}
        1 : <CFString 0x7328130 [0x2724380]>{contents = "MyEntityNameTwo"} = <CFData 0x7328200 [0x2724380]>{length = 32, capacity = 32, bytes = 0x0ca6ecf1283d12bd3ca82af39b6b9f5d ... 149dd39a591e0c4d}
        ...    }
    

    应该很容易遍历 NSStoreModelVersionHashes 字典并记录您的商店所需的版本哈希。

    手动将其与VersionInfo.plist 中可用的匹配,看看缺少什么。也许没有一个模型包含现有持久存储中所有必需的实体版本。这可能是由于(意外?)在设置新模型版本之前或之后对模型进行了编辑?

    【讨论】:

    • 你能给我一个链接,告诉我如何在运行时列出应用程序包中的所有可用模型吗?我在这些条款上没有太多运气谷歌搜索。谢谢!
    • 感谢这些步骤 - 我用更多信息编辑了我的原始问题,但仍然很难过。
    • 你能验证加载所需模型的那个版本吗?如果它确实加载了,并且您可以使用它为您的商店启动 NSPersistentStoreCoordinator,这可能是自动轻量级迁移的一个古怪错误?
    • 我在这个问题上悬赏,因为我有完全相同的问题。想要对其进行排序。
    • 解决了我的问题,添加了新的答案。
    【解决方案3】:

    我遇到了 esilver 的确切问题,并通过 Google 找到了这个问题。但是,对我有用的修复在 SO 上没有其他任何地方(我知道),所以这里是:

    如果您的捆绑包中有多个 *.mom 文件(已编译的对象模型)副本,Core Data 可能会在您尝试迁移时感到困惑。

    我们的问题是,每个单独的模型文件(Data.xcdatamodelData_V1.xcdatamodelData_V2.xcdatamodel 等)不仅位于 xcdatamodeld/ 目录中(在构建过程中作为要编译的内容包含在内),而且每个文件也都包含在“编译源”列表中。

    这意味着生成的包有两组*.mom 文件:一组在xcdatamodeld/ 内部,一组在顶层。我认为 Core Data 变得非常非常混乱,并导致了这个错误。从“编译源”中删除每个xcdatamodel 文件并离开xcdatamodeld 目录为我们解决了问题(例如,启动并再次运行自动版本控制)。希望这会有所帮助!

    【讨论】:

    • 这个“编译源”列表在哪里?
    • 编译源代码位于底部左侧的文件导航器(Xcode 3.2.x)中,在“targets”内部,在 Xcode 4 上,单击项目文件名,然后构建阶段,然后编译源代码。
    【解决方案4】:

    在我的情况下,完全相同的事情正在发生,我在 iOS 7 上,这个问题让我头疼了至少一个星期,然后终于找到了适合我的解决方案 . 为了让它工作,你必须在选项中添加一个额外的值,用于添加 PersistentStore,然后你就可以去了(我不确定其他 iOS 版本,但它肯定会在 iOS 7 上工作)。

    -(NSManagedObjectModel *)managedObjectModel
    {
        if (managedObjectModel != nil)
        {
            return managedObjectModel;
        }
        managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
        return managedObjectModel;
    }
    
    -(NSPersistentStoreCoordinator *)persistentStoreCoordinator
     {
    
       if (persistentStoreCoordinator != nil)
       {
           return persistentStoreCoordinator;
       }
    
        NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"ABC.sqlite"];
    
        NSError *error = nil;
        persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] ini   tWithManagedObjectModel:[self managedObjectModel]];
    
    //Creating Lightweight migration.
        NSDictionary *options =
        @{
          NSMigratePersistentStoresAutomaticallyOption:@YES
          ,NSInferMappingModelAutomaticallyOption:@YES
          ,NSSQLitePragmasOption: @{@"journal_mode": @"DELETE"}
         };
    
    
       if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
        {
           NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
           abort();
        }
    return persistentStoreCoordinator;
    }
    

    【讨论】:

      【解决方案5】:

      伙计们,

      为了记录,我完全停止使用核心数据。我的代码很复杂,而且根据上述问题,不可靠。我现在直接使用 SQLLite 并且更快乐。我不建议在任何情况下使用 Core Data。

      【讨论】:

      • 我也对 Core Data 感到非常恼火。当出现问题时,“神奇”的数据迁移过程是〜方式〜太不透明了。我没有在一个地方找到足够的详细信息来移除封面并深入了解我在数据迁移方面遇到的问题。
      • 您不应将“我不懂 API”误认为“它太复杂了”。使用 SQL 和 Core Data 后,后者总体上是更简单的 API,尤其是随着应用程序变得越来越复杂。我认为您的问题是由尝试迁移开发版本引起的,尤其是尝试迁移已经失败的文件。
      • 根据我的经验,这并不是“太复杂”,API 完全不符合规范。核心数据非常适合具有简单迁移需求的玩具应用;正如您从我的问题和此页面上的其他 cmets 中看到的那样,自动迁移在一定程度的复杂性下会崩溃。也许他们已经修复了它,但我不会回去,因为 SQLite 既有效又易于理解。
      • 作为一个拥有 35 个不同模型版本的应用程序的核心数据的重度用户,我可以很高兴地说,这个答案比核心数据差 10 倍。是的,它可能会引起一些头痛,但它们的存在是有原因的。 Core Data 很强大,只要你正确使用它。鼓吹别人因为你不喜欢就拒绝使用,甚至仅仅因为它复杂就拒绝使用,对大众都是不利的。正确的答案应该是如何解决您的问题。不要全部扔掉。
      • 更新:显然开发社区分享了我对这项技术的经验:news.ycombinator.com/item?id=5454491
      猜你喜欢
      • 2014-07-06
      • 1970-01-01
      • 2016-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-27
      • 1970-01-01
      相关资源
      最近更新 更多