29

我有一个 iOS 应用程序,它在钥匙串中存储了一些敏感信息。在将值写入钥匙串时,我收到错误代码 -34018。

我目前正在使用 Apple 的 iOS KeyChainItemWrapper 类。

以下两行代码都收到相同的错误代码。

OSStatus res1 = SecItemCopyMatching((__bridge CFDictionaryRef)genericPasswordQuery, (CFTypeRef *)&attributes);
OSStatus res = SecItemUpdate((__bridge CFDictionaryRef)updateItem, (__bridge CFDictionaryRef)tempCheck);

此问题并非每次都会出现,而是间歇性出现。一旦我收到此错误,我将无法再将任何值写入钥匙串。

我已经打印了这样的错误描述:

NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:res userInfo:nil];

这就是错误打印出来的内容:

Error: Error Domain=NSOSStatusErrorDomain Code=-34018 "The operation couldn’t be completed. (OSStatus error -34018.)"
4

8 回答 8

35

似乎这是钥匙串中的一个错误,仅当您从 xcode 启动应用程序时才会出现。见这里:https ://github.com/soffes/sskeychain/issues/52

我们对其进行了很多调试,当应用程序从后台启动时访问钥匙串似乎存在问题。这只发生在调试器上(即从 Xcode 启动时)。我们认为这个问题在我们的案例中可能与调试器保持应用程序保持活动有关,即使它应该被操作系统杀死。实际上,我们尝试运行该应用程序,然后将其置于后台并启动许多其他应用程序以占用 RAM。使用调试器从后台恢复应用程序时会出现错误,而没有调试器则不会出现(我们每个都运行了至少 10 个测试)。

于 2015-01-31T21:14:05.217 回答
32

如果有人会带着这个错误和XCode8回到这里,可能你必须在选项卡中启用KeyChain ShareCapabilities

激活钥匙串共享 在此处输入图像描述

于 2016-10-19T08:00:33.647 回答
5

正如其他人所提到的,这是一个 Keychain 错误,Apple 至少从 2015 年年中就已经意识到并且已经意识到了这一错误。

然而,截至 2016 年 3 月 22 日,Apple 表示:

我们相信这些问题在 iOS 9.3 中得到了解决。

iOS 9.3 于 2016 年 3 月 21 日发布。

请参阅线程:https ://forums.developer.apple.com/thread/4743

引用 Apple 员工的回复:

2016 年 3 月 22 日凌晨 3 点 28 分

好的,这是最新的。这是一个复杂的问题,有多种可能的原因:

  • 该问题的某些实例是由不正确的应用签名引起的。您可以轻松区分这种情况,因为问题是 100% 可重现的。

  • 该问题的某些实例是由 iOS 支持应用程序开发的错误引起的 (r. 23,991,853)。由于操作系统中的另一个错误 (r. 23,770,418) 掩盖了它的影响,因此调试这个问题变得复杂,这意味着问题仅在设备处于内存压力下时才会出现。

    我们相信这些问题在 iOS 9.3 中得到了解决。

  • 我们怀疑这个问题可能还有更多的原因。

因此,如果您在运行 iOS 9.3 或更高版本的用户设备(Xcode 尚未与之交谈的设备)上发现此问题,请提交有关它的错误报告。尝试在您的错误报告中包含设备系统日志(我意识到在处理客户设备时可能会很棘手;一种选择是要求客户安装 Apple Configurator,这样他们就可以查看系统日志)。如果您确实提交了错误,请发布您的错误编号,以供记录。

我代表 Apple 感谢大家为帮助追查这个相当可怕的问题所做的努力。

分享和享受

于 2016-03-22T21:09:24.107 回答
3

这让我等了 2 个小时才找到一个快速的“修复”——重启 iOS 设备

引用http://forums.developer.apple.com/thread/4743的讨论,

来自用户的小细节

正如其他人所报告的那样,当通过附带调试器的 Xcode 启动时,最容易观察到这个神秘的钥匙串错误。一旦错误开始发生,无论内存压力如何,钥匙串似乎都不会自行恢复,直到重新启动设备

当我重新启动设备时,错误消失了,让我可以继续测试。不知道还能做什么。在我的情况下,不可能迁移到 NSUserDefaults 或其他一些存储解决方案。

于 2015-10-15T01:17:17.963 回答
2

我正在使用来自苹果的 GenericKeychain 类:

https://developer.apple.com/library/content/samplecode/GenericKeychain/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007797-Intro-DontLinkElementID_2

struct KeychainConfiguration {

static let serviceName = "MyAppService"



/*

    Specifying an access group to use with `KeychainPasswordItem` instances will create items shared accross both apps.



    For information on App ID prefixes, see:

        https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/AppID.html
    and:
        https://developer.apple.com/library/ios/technotes/tn2311/_index.html
*/

//    static let accessGroup = "[YOUR APP ID PREFIX].com.example.apple-samplecode.GenericKeychainShared"



/*

    Not specifying an access group to use with `KeychainPasswordItem` instances

    will create items specific to each app.

*/

static let accessGroup: String? = nil

}

在这个文件中,我在这一行中指定了我的自定义 accessGroup static let accessGroup = "[YOUR APP ID PREFIX].com.example.apple-samplecode.GenericKeychainShared"

返回静态后让 accessGroup:String? = nil问题消失了。:)

于 2017-12-06T15:32:23.783 回答
2

使用钥匙串解决此问题的一种方法是使用 dispatch_async 来允许应用程序启动。这在从后台打开应用程序时有效。还要确保您kSecAttrAccessibleAfterFirstUnlock在钥匙串上有可访问性设置。

 dispatch_async(dispatch_get_main_queue(), ^{
    // save/write to keychain
 })
于 2015-09-11T15:42:31.423 回答
1

确保钥匙串共享必须项目Target的Capabilities下。

在我的情况下,App_Name.entitlements 文件的包 ID 与我的项目包 ID 不同。因此,我将 App_Name.entitlements 文件中的包 ID 更改为我的项目包 ID。例如,假设您的项目包 id 是 com.Apple.testApp 然后到

  1. App_Name.entitlements 文件打开密钥 Keychain Access Groups 密钥,它是 Array 类型的。
  2. 在 item0 下设置项目捆绑 ID 的值,例如:- $(AppIdentifierPrefix)com.Apple.testAp。
于 2018-10-10T13:46:41.800 回答
0

根据@iCaramba 的回答。我找到了一种解决方法:

  1. 停止任务以终止应用程序(如果您已经在运行应用程序)
  2. 在您的设备上手动启动该应用程序。不要使用 Xcode
  3. 使用 Xcode 重新启动应用程序
于 2015-11-29T16:13:11.613 回答