gpt4 book ai didi

ios - 将 SQL 存储添加到 NSPersistentStoreCoordinator 时如何调试/处理间歇性 "authorization denied"和 "disk i/o"错误?

转载 作者:IT王子 更新时间:2023-10-29 08:03:11 34 4
gpt4 key购买 nike

我在应用商店中有一个应用,我正在使用日志记录服务来获取崩溃日志和相关的日志数据。我看到间歇性崩溃(受影响的用户数量很少,每个用户的崩溃数量也很少),但这让我感到困惑。

这些崩溃发生的情况如下:

  1. 应用启动并初始化核心数据栈

  2. 应用程序尝试使用以下代码(storeURL 有效)将 SQL 存储添加到 NSPersistentStoreCoordinator:

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

    sqlStore = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
    configuration:nil
    URL:storeURL
    options:options
    error:&error];
  3. 添加该店铺时出现以下错误之一:

NSError:

Domain=NSCocoaErrorDomain
Code=256 "The operation couldn’t be completed. (Cocoa error 256.)"
UserInfo=0x1dd946a0 {NSUnderlyingException=authorization denied, NSSQLiteErrorDomain=23}

NSError:

Domain=NSCocoaErrorDomain
Code=256 "The operation couldn’t be completed. (Cocoa error 256.)"
UserInfo=0xc6525d0 {NSUnderlyingException=disk I/O error, NSSQLiteErrorDomain=10}

在这种情况下,应用程序将崩溃 b/c 应用程序运行需要 SQL 存储。我可以尝试通过尝试新的 storeURL 来优雅地处理此故障,但我不希望用户丢失现有数据。此外,我从未亲自重现此问题,并且根据受影响的用户数量和崩溃日志,我认为这是一个影响较小的问题,不会在后续应用程序启动时再次出现。

我希望有一位 Core Data 大师可以就如何调试和预防/处理这些情况提出一些建议。我的核心数据堆栈初始化代码直接来自 xcode 项目生成器,我已经排除了任何并发问题,因为持久存储协调器仅初始化一次(启动时),并且此错误发生在该初始化中。

如果相关,很乐意提供更多代码/信息。

谢谢!

最佳答案

看来 XJones 和我已经找到了原因。它似乎是 iOS 边缘案例错误或未记录的行为。我已将其归档在 Apple 错误 ID 12935031 下。

有一个无法解释的场景,即使用 Core Location 显着位置变化或区域监控的应用程序可能无法正常启动(或产生其他意想不到的后果),因为从 iOS 5 开始,Core Data 存储使用数据保护(默认加密)。

重现步骤:

1) 在设备上开启密码保护

2) 创建一个启动重要位置监控或区域监控的应用程序,即使在后台也能保持启动状态。 IE。使用后台显着位置更改或区域监控的应用。

3)等待设备上的电池电量耗尽(也可能有其他原因)

4) 设备将关闭

5) 将设备连接到 Mac

6) 电量充足后,设备将启动。重要提示:此时不要解锁设备。

7) 退出或进入监控范围或导致位置发生重大变化。该设备现在将自动重新启动该应用程序,因为它注册了重要位置监控或区域监控

8) 但是,由于用户尚未解锁设备(尚未输入密码),应用程序将无法读取其任何 protected 数据文件。在 Core Data 应用程序中,这将导致持久存储协调器无法将持久存储文件添加到托管对象上下文。这将导致应用程序崩溃,或者根据开发人员使用的代码甚至尝试重置数据库。在其他应用程序中,它可能会由于其他原因导致崩溃,因为这是 iOS 5 及更高版本中默认为核心数据存储打开的数据保护功能的意外、未记录的副作用。

在 Apple 更正此问题或至少记录它之前的解决方案或变通方法是确保您的应用程序停止监视 applicationWillTerminate 中的重要位置更改/区域或 通过为 NSFileProtectionKey 设置 NSFileProtectionNone 来关闭默认数据保护功能将核心数据存储添加到持久存储协调器时在选项字典中输入键。 使用 while() 循环检查 protected 数据是否可用,以等待文件存储可用。使用 KVO 可能还有其他方法可以做到这一点,但这种方法工作可靠,并且最容易插入现有代码,而无需重新处理整个应用程序启动过程。

更新:如果数据保护已在商店中激活,那么仅仅设置该 key 似乎是不够的。你必须手动设置它:

<strike></strike>

<strike>

<pre><code>[[NSFileManager defaultManager] setAttributes:[NSDictionary dictionaryWithObject:NSFileProtectionNone forKey:NSFileProtectionKey] ofItemAtPath:storePath error:nil];
</code></pre>

</strike>

<strike></strike>

由于 XJones 的更多输入以及对 Apple 分散文档的更多研究,这是需要后台位置监控的应用程序的修复:



<pre><code>while(![[UIApplication sharedApplication] isProtectedDataAvailable]) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5f]];
}
</code></pre>

此代码在您尝试将存储数据文件添加到持久存储协调器之前进入。

2015 年更新:您还可以将 NSPersistentStoreFileProtectionKey 设置为 NSFileProtectionNone。这将正确禁用文件保护(如果您不需要它)并且无需任何变通方法即可正常工作。它在之前的尝试中不起作用的原因是我测试的字典键不正确。

关于ios - 将 SQL 存储添加到 NSPersistentStoreCoordinator 时如何调试/处理间歇性 "authorization denied"和 "disk i/o"错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12845790/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com