核心数据处理不当,轻量级迁移会导致反复崩溃吗?

Can improper handling of core data light weight migration lead to recurrent crashes?

提问人:Sandeep Bhandari 提问时间:11/3/2023 最后编辑:Sandeep Bhandari 更新时间:11/4/2023 访问量:38

问:

上下文:

我正在开发一个遗留代码库。应用程序将核心数据用于一个非常简单的用例。核心数据栈是使用 Objective-C 设置的

- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator) {
        _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }

    return _managedObjectContext;
}

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

    @synchronized(_persistentStoreCoordinator) {

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

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

        if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                       configuration:nil
                                                                 URL:self.storeURL
                                                             options:nil
                                                               error:&error])
        {

            NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption : @(YES),
                                      NSInferMappingModelAutomaticallyOption       : @(YES)};

            if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:self.storeURL options:options error:&error]) {

                [[NSFileManager defaultManager] removeItemAtURL:self.storeURL error:nil];

                if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:self.storeURL options:options error:&error]) {
                    abort();
                }
            }
        }

    }
    return _persistentStoreCoordinator;
}

显然,初始化代码是从苹果的核心数据示例(旧核心数据示例)中复制而来的。persistentStoreCoordinator

2019 年,修改了核心数据架构,在核心数据实体中增加了 2 个新属性,没有处理核心数据轻量级迁移。这应该会导致大量应用程序崩溃,但不幸的是,它从未被注意到。自 2019 年以来,已经发布了多个应用程序更新,但没有解决问题。即使在 2023 年的今天,我们目前每周也看到 20K 崩溃。

问题:

  1. 显然,在不处理核心数据的情况下修改核心数据架构 轻量级迁移一定是导致 2019 年崩溃的原因,但从那时起,核心数据没有任何变化,如果我们假设 app - v.201 发生了核心数据更改并导致了崩溃,之后 v.202,v.203....在没有进行任何更改的情况下发布,崩溃还会因此而发生吗?

  2. 如果它是由于 2019 年所做的更改而发生的,并且我现在必须修复它,我是否可以简单地从架构中删除这两个字段并通过创建新版本的架构并处理轻量级迁移来添加它们,这行得通吗?我能做些什么来解决这个问题。

PS:不幸的是,由于初始化的方式,当控件执行abort()语句时会发生崩溃,因此我们无法捕获实际错误persistentStoreCoordinator

编辑1:

不幸的是,我们的崩溃报告工具没有捕获到此崩溃,我在 xcode 中观察到此崩溃(xcode-> organizer-> 崩溃),并且由于它没有被崩溃报告工具捕获,我不得不使用 atos 命令手动符号化崩溃,所以这里是崩溃发生的前几行符号化

-[StoreController persistentStoreCoordinator] (in blabla) (StoreController.m:220)
0x0000000100000000 (in blabla)
-[StoreController managedObjectContext] (in blabla) (StoreController.m:142)
0x0000000100000000 (in blabla)
+[StoreController storeControllerWithStoreURL:andModelURL:] (in blabla) (StoreController.m:58)
0x0000000100000000 (in blabla)
-[Core storeController] (in blabla) (Core.m:81)
0x0000000100000000 (in blabla)
IPhoneAppDelegate.setupLibraries(in:) (in blabla) + 80
0x0000000100000000 (in blabla)
IPhoneAppDelegate.application(_:willFinishLaunchingWithOptions:) (in blabla) + 12
0x0000000100000000 (in blabla)
@objc IPhoneAppDelegate.application(_:willFinishLaunchingWithOptions:) (in blabla) + 120
0x0000000100000000 (in blabla)

从崩溃日志中,我们可以看到

  1. willFinishLaunchingWithOptions我们调用一个方法setupLibraries
  2. 在内部访问名为storeController
  3. 哪 内部调用storeControllerWithStoreURL
  4. 尝试访问属性managedObjectContext
  5. 调用属性初始化(我在上面提供的代码)persistentStoreCoordinator

在第 220 行,我们有声明abort();

Objective-C 核心 核心数据迁移

评论

0赞 Tom Harrington 11/4/2023
您有关于崩溃的哪些类型的崩溃日志、错误消息或其他详细信息?它们通常包含解决问题的重要线索。
0赞 Sandeep Bhandari 11/4/2023
@TomHarrington不幸的是,我们的崩溃报告工具没有捕获到此崩溃,我在 xcode 中观察到了此崩溃(xcode-> organizer-> 崩溃),并且因为它没有被崩溃报告工具捕获,我不得不使用 atos 命令手动符号化崩溃,所以这里是崩溃发生的前几行符号化,将更新问题
0赞 Sandeep Bhandari 11/4/2023
我已经稍微编辑了类和方法名称,因此您在崩溃日志中看到荒谬的blabla:)但正如我之前提到的,这是我拥有的实际崩溃日志,如果崩溃是由于 coredata 异常/错误而发生的,我们会得到正确的崩溃日志,但崩溃是由于 abort() 语句而发生的,我的问题是为什么 abort() 语句会为较新的应用程序版本运行?在 2019 年,我们在没有处理迁移的情况下修改了架构,这应该会导致下一个版本崩溃,但之后的版本不应该崩溃,对吗?自 2019 年以来,我们的核心数据没有变化

答: 暂无答案