随机错误:用于打开商店的模型与用于创建商店的模型不兼容

发布于 2025-02-04 19:33:26 字数 7106 浏览 4 评论 0原文

我一直在努力处理Coredata错误,例如“用于开设商店的模型与我的生产应用程序中用于创建商店的商店不兼容”。

简而言之。 我有带有Coredata的应用程序,请使用Objective-C。该应用在AppStore中。和Firebasecrashlytics为某些用户展示了“用于打开商店的模型不兼容”。

我已经阅读了许多主题,我知道原因可能是从一种模型到另一种模型的迁移。是的,我有8次更改模型。通常进行轻巧的迁移。

但是有一些奇怪的项目:

  1. 此错误仅针对某些随机时间发生。
  2. 如果发生错误,应用程序崩溃。没关系。但是用户可以第二次或第三次运行,并且不会发生错误。该应用程序运行良好。在某些情况下,用户必须重新加载设备在不会崩溃的情况下运行应用程序。重新加载可以帮助100%的用户。
  3. 在我自己的设备上,它仅发生1-2次,持续2年。我无法在Xcode上捕获此情况。
  4. 它不取决于模型设备或iOS版本。
  5. 该应用程序存在大约6年。它开始发生2-3版(模型)更改AGO。

代码详细信息:

我在ViewDidload中加载“ PersistentContainer”(也尝试在AppDelegate中加载相同情况):

- (void)viewDidLoad {
        [super viewDidLoad];
        
        errorPersistentContainer= [[DataAccess sharedInstance]  getPersistentContainerWithResult]; 
        if ( errorPersistentContainer!=nil){ 
             
            [[FIRCrashlytics crashlytics] log:errorPersistentContainer.userInfo.description];
            [[FIRCrashlytics crashlytics] recordError:errorPersistentContainer]; 
            
            UIAlertController * alertController = [UIAlertController alertControllerWithTitle:nil message:@"error" preferredStyle:UIAlertControllerStyleAlert];
            
            [alertController addAction:[UIAlertAction actionWithTitle: @"Ок" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
                 
                //try second time!!
                errorPersistentContainer= [[DataAccess sharedInstance] getPersistentContainerWithResult_SecondTime]; 
                if (errorPersistentContainer!=nil){ //error again 
                    [self showDataAccessError];
                } else {//Everything is OK
                    [self initTabToday]; 
                }
                
            }]];
            [self presentViewController:alertController animated:YES completion:nil];
        }else { //Everything is OK
            [self initTabToday];
        }
        
    }

== DataAccess.m

- (NSError*) getPersistentContainerWithResult_SecondTime {
    _persistentContainer = nil;
    return  [self getPersistentContainerWithResult];
}
//загружаем persistent Container
- (NSError*) getPersistentContainerWithResult { 
    __block NSError *errorResult=nil;
    @synchronized (self) {
        if (_persistentContainer == nil) {
            _persistentContainer = [[NSPersistentContainer alloc] initWithName:@"app_base"];
            
            NSURL *storeURL=[self getStoreURLWithFile]; 
   
            //migrate to app group (use embedded widget)
            if ( [[NSFileManager defaultManager] fileExistsAtPath:storeURL.path] == NO) {
                [self migrateToGroup:_persistentContainer.persistentStoreCoordinator];
            } else {
                NSPersistentStoreDescription *storeDescription=[[NSPersistentStoreDescription alloc] initWithURL:storeURL]; 
                _persistentContainer.persistentStoreDescriptions = @[storeDescription];
 
                [self.persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *description, NSError *error) {
                    if (error != nil) {
                        errorResult=error;
                    } else {
                        [self.persistentContainer.viewContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
                    }
                    KSLog(@"initPersistentContainer done complete");
                }];
                KSLog(@"initPersistentContainer done after");
            }
        }
    }
 
    return errorResult;
}

-(void) migrateToGroup:(NSPersistentStoreCoordinator*)coordinator {
    KSLog(@"migrateToGroup");
    NSError *error = nil;
    NSDictionary *storeOptions = [NSDictionary dictionaryWithObjectsAndKeys:
                                  [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                                  [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
    
    NSPersistentStore  *sourceStore        = nil;
    NSPersistentStore  *destinationStore   = nil;
    
    NSURL *oldStoreURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    oldStoreURL = [oldStoreURL URLByAppendingPathComponent:@"app_base.sqlite"];
    
    
    NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:[self currentContainer]];
    storeURL = [storeURL URLByAppendingPathComponent:@"app_base.sqlite"];
     
    // Add the source store
    if (![coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:oldStoreURL options:storeOptions error:&error]){ 

    } else {
        sourceStore = [coordinator persistentStoreForURL:oldStoreURL];
        if (sourceStore != nil){
            // Perform the migration
            destinationStore = [coordinator migratePersistentStore:sourceStore toURL:storeURL options:storeOptions withType:NSSQLiteStoreType error:&error];
            if (destinationStore == nil){
                // Handle the migration error
                NSLog(@"the migration error"); 
            } else {
                NSLog(@"ok - can remove old");
              
            }
        }
    }
    
}

===================================

nsunderlyingerror =“错误域= nscocoaerrordomain code = 134100 “用于打开持久存储的托管对象模型版本 与用于创建持久性的那个不兼容 商店。“ userInfo = {metadata = {\ n nspersistenceFrameWorkversion = 1048; \ n n nsstoremodeLversionhashes = {\ n friends = {长度= 32,字节= 0xA4233393 C2464286 0847EFB8 92C58968 ... 49ACB261 34EA84A8}; \ n目标= {长度= 32,字节= 0x01145946 55708FF8 62354BD8 96312A81 ... 0F993736 D465C5C8}; \ n
kssettings = {长度= 32,字节= 0x4A4FF768 95D9D482 5442F0B4 3C3F4932 ... 5E5683FE 0F9E37F1}; \ n list = {length = 32,字节 = 0x685A284A 56B681AB 8C90D929 1DB22048 ... 52604C30 A373F09A}; \ n NOTE = {长度= {长度= 32,bytes = 0xD5C0A494 8359F711 626842C2 D21B2 D21B88DE ... 661E0C0C 50DC480F}; \ n共享= {长度= 32,bytes = 0xBDA79A1A 80065C47 9B964696 59F09F43 ... EC6601E2 A695220C}; \ n
stat = {长度= 32,字节= 0xCE86D983 D05F4F7A EC4680F0 4FAB7818 ... DFE3310B 5DF27156}; \ n tags = {length = 32,字节= 0x06919599 E01FB1BF AE276BC5 490A754A ... 1AD63318 E9B19428}; \ n
“ tags_tasks” = {长度= 32,字节= 0x11b2b407 f472c1c7 460764df 53249c6b ... 27fb84fd C0787398}; \ n task = {长度= 32,字节 = 0x3C77D29D D0EB7338 55DA69B9 B1C555118 ... C66D3888 1075E598}; \ n}; \ \ n nSstoremodeModeLversionHashesdigest = QWRSU1ZGW2BCEQ1CGXTDPIOZXPLTVJB4PRZ7IDU/BSTANEDQH1U8CLXPU1MBIEUX1RI3UNWL4+Z7R/KJFRN/KJFRN/NW ====“; \ n nsstoremodeLversionhashesversion = 3; \ n
nsstoremodeLversionIdentifiers =(\ n“” \ n); \ n
nsStoreType = sqlite; \ n nsstoreuuid = “ 8D0217C5-992C-4B08-B11E-30ED01F5A089”; \ n“ _nsautovacuumlevel” = 2; \ n},原因=用于打开商店的模型与用于创建商店的一个模型不兼容}}; 原因=“未能打开商店”;

==在某些以前的版本中有错误

“此NspersistentStoreCoorDinator没有持久的商店(架构 不匹配或迁移失败)。它无法执行保存操作。”

我将非常感谢任何想法和解决方案。 如何解决核心数据模型的问题,或者可能是我的加载代码是错误的? 是否可以找出用于打开用于创建商店的模型之间的商店的模型中的区别?

I have been struggling with CoreData errors like "The model used to open the store is incompatible with the one used to create the store" in my production app for year.

In short.
I have the app with CoreData, use objective-c. The app is in AppStore. And FirebaseCrashlytics shows for some users "The model used to open the store is incompatible".

I've read many topics and I understand reason can be wrong migration from one model to another. Yes, I had 8 times changing model. And usually did lightweight migration.

But there are strange items :

  1. This error occurs only for some users in random times.
  2. If error occurs the app crashes. It's ok. But an user can run second or third time and error doesn't occur. The app works well. In some cases user must reload device to run the app without crash. Reloading helps 100% users.
  3. On my own devices it happens only 1-2 time for 2 years. I not able to catch this case on Xcode.
  4. It's not depend on model device or iOS version.
  5. The app exists about 6 years. It started to happen 2-3 version (model) changing ago.

Code details:

I load "persistentContainer" in viewDidLoad (also tried load in AppDelegate the same situation):

- (void)viewDidLoad {
        [super viewDidLoad];
        
        errorPersistentContainer= [[DataAccess sharedInstance]  getPersistentContainerWithResult]; 
        if ( errorPersistentContainer!=nil){ 
             
            [[FIRCrashlytics crashlytics] log:errorPersistentContainer.userInfo.description];
            [[FIRCrashlytics crashlytics] recordError:errorPersistentContainer]; 
            
            UIAlertController * alertController = [UIAlertController alertControllerWithTitle:nil message:@"error" preferredStyle:UIAlertControllerStyleAlert];
            
            [alertController addAction:[UIAlertAction actionWithTitle: @"Ок" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
                 
                //try second time!!
                errorPersistentContainer= [[DataAccess sharedInstance] getPersistentContainerWithResult_SecondTime]; 
                if (errorPersistentContainer!=nil){ //error again 
                    [self showDataAccessError];
                } else {//Everything is OK
                    [self initTabToday]; 
                }
                
            }]];
            [self presentViewController:alertController animated:YES completion:nil];
        }else { //Everything is OK
            [self initTabToday];
        }
        
    }

== DataAccess.m===

- (NSError*) getPersistentContainerWithResult_SecondTime {
    _persistentContainer = nil;
    return  [self getPersistentContainerWithResult];
}
//загружаем persistent Container
- (NSError*) getPersistentContainerWithResult { 
    __block NSError *errorResult=nil;
    @synchronized (self) {
        if (_persistentContainer == nil) {
            _persistentContainer = [[NSPersistentContainer alloc] initWithName:@"app_base"];
            
            NSURL *storeURL=[self getStoreURLWithFile]; 
   
            //migrate to app group (use embedded widget)
            if ( [[NSFileManager defaultManager] fileExistsAtPath:storeURL.path] == NO) {
                [self migrateToGroup:_persistentContainer.persistentStoreCoordinator];
            } else {
                NSPersistentStoreDescription *storeDescription=[[NSPersistentStoreDescription alloc] initWithURL:storeURL]; 
                _persistentContainer.persistentStoreDescriptions = @[storeDescription];
 
                [self.persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *description, NSError *error) {
                    if (error != nil) {
                        errorResult=error;
                    } else {
                        [self.persistentContainer.viewContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
                    }
                    KSLog(@"initPersistentContainer done complete");
                }];
                KSLog(@"initPersistentContainer done after");
            }
        }
    }
 
    return errorResult;
}

-(void) migrateToGroup:(NSPersistentStoreCoordinator*)coordinator {
    KSLog(@"migrateToGroup");
    NSError *error = nil;
    NSDictionary *storeOptions = [NSDictionary dictionaryWithObjectsAndKeys:
                                  [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                                  [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
    
    NSPersistentStore  *sourceStore        = nil;
    NSPersistentStore  *destinationStore   = nil;
    
    NSURL *oldStoreURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    oldStoreURL = [oldStoreURL URLByAppendingPathComponent:@"app_base.sqlite"];
    
    
    NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:[self currentContainer]];
    storeURL = [storeURL URLByAppendingPathComponent:@"app_base.sqlite"];
     
    // Add the source store
    if (![coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:oldStoreURL options:storeOptions error:&error]){ 

    } else {
        sourceStore = [coordinator persistentStoreForURL:oldStoreURL];
        if (sourceStore != nil){
            // Perform the migration
            destinationStore = [coordinator migratePersistentStore:sourceStore toURL:storeURL options:storeOptions withType:NSSQLiteStoreType error:&error];
            if (destinationStore == nil){
                // Handle the migration error
                NSLog(@"the migration error"); 
            } else {
                NSLog(@"ok - can remove old");
              
            }
        }
    }
    
}

==== error from crashlytics ====

NSUnderlyingError = "Error Domain=NSCocoaErrorDomain Code=134100
"The managed object model version used to open the persistent store
is incompatible with the one that was used to create the persistent
store." UserInfo={metadata={\n NSPersistenceFrameworkVersion =
1048;\n NSStoreModelVersionHashes = {\n Friends =
{length = 32, bytes = 0xa4233393 c2464286 0847efb8 92c58968 ...
49acb261 34ea84a8 };\n Goal = {length = 32, bytes = 0x01145946
55708ff8 62354bd8 96312a81 ... 0f993736 d465c5c8 };\n
KSSettings = {length = 32, bytes = 0x4a4ff768 95d9d482 5442f0b4
3c3f4932 ... 5e5683fe 0f9e37f1 };\n List = {length = 32, bytes
= 0x685a284a 56b681ab 8c90d929 1db22048 ... 52604c30 a373f09a };\n Note = {length = 32, bytes = 0xd5c0a494 8359f711 626842c2 d21b88de ...
661e0c0c 50dc480f };\n Shared = {length = 32, bytes =
0xbda79a1a 80065c47 9b964696 59f09f43 ... ec6601e2 a695220c };\n
Stat = {length = 32, bytes = 0xce86d983 d05f4f7a ec4680f0 4fab7818 ...
dfe3310b 5df27156 };\n Tags = {length = 32, bytes = 0x06919599
e01fb1bf ae276bc5 490a754a ... 1ad63318 e9b19428 };\n
"Tags_Tasks" = {length = 32, bytes = 0x11b2b407 f472c1c7 460764df
53249c6b ... 27fb84fd c0787398 };\n Task = {length = 32, bytes
= 0x3c77d29d d0eb7338 55da69b9 b1c55118 ... c66d3888 1075e598 };\n };\n NSStoreModelVersionHashesDigest =
"qWrsu1ZGw2BcEQ1cgxtdpioZxPlTVJb4Prz7iDU/BStANEdQh1u8clXpu1mbIeUx1ri3Unwl4+z7r/KjfRN/nw==";\n
NSStoreModelVersionHashesVersion = 3;\n
NSStoreModelVersionIdentifiers = (\n ""\n );\n
NSStoreType = SQLite;\n NSStoreUUID =
"8D0217C5-992C-4B08-B11E-30ED01F5A089";\n "_NSAutoVacuumLevel"
= 2;\n}, reason=The model used to open the store is incompatible with the one used to create the store}";
reason = "Failed to open the store";

== In some previous version there was error

"This NSPersistentStoreCoordinator has no persistent stores (schema
mismatch or migration failure). It cannot perform a save operation."

I will be very grateful for any ideas and solutions.
How can I solve problem with Core data model or may be my loading code is wrong?
Is it possible to find out what the difference in The model used to open the store between model used to create the store?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文