调用钥匙串服务失败并显示错误Sec不可用使用命令行工具执行目标并且 iPhone 模拟器设置为硬件版本 6.0 (10A403) 时。如果我将模拟器版本更改为其他以前的版本(4.3、5.0、5.1)并使用相同的命令行脚本重新执行,则调用会成功。
我正在运行最新的 XCode 4.5,并且命令行工具是从 XCode 中下载的。
要重现此错误,只需执行以下操作:
- 使用 OCUnit 目标设置 ios 库项目
- 将基础 SDK 设置为 6.0
- 将 iOS 部署目标设置为 4.3
- 将帖子末尾的代码复制并粘贴到测试项目中(它只会尝试存储密码并检索它)
- 将 Security.framework 添加到 OCUnit 目标
在 XCode 中执行 OCUnit 目标,并使用 iPhone 模拟器中设置的任何硬件版本查看测试通过情况(只需在执行之间更改它)。
使用以下命令从命令行执行 OCUnit 目标:
xcodebuild -target TARGET_NAME_HERE -sdk iphonesimulator -configuration Release TEST_AFTER_BUILD=YES
将 iPhone 模拟器设置为硬件版本 6.0,测试将fail。如果将 iPhone 模拟器硬件版本更改为 4.3、5.0 或 5.1 并再次执行命令行脚本,测试将succeed.
这是命令行工具的问题吗? iphone模拟器有问题吗?从命令行运行 OCUnit 目标有问题吗?
谁喜欢只有当彗星对齐时才能通过的单元测试?
有任何想法吗?
这是代码:
#define KEYCHAIN_ITEM_ATTRIBUTES (id)kSecClassGenericPassword, kSecClass, @"MyService", kSecAttrService, @"MyPassword", kSecAttrAccount
const NSString* MyPassword = @"blabla";
- (void)testExample
{
// remove previous keychain item
OSStatus status = SecItemDelete((CFTypeRef)[NSDictionary dictionaryWithObjectsAndKeys:KEYCHAIN_ITEM_ATTRIBUTES, nil]);
NSLog(@"SecItemDelete status:%ld",status);
NSParameterAssert(status == errSecSuccess || status == errSecItemNotFound);
// add keychain item with new value
NSData *data = [MyPassword dataUsingEncoding:NSUTF8StringEncoding];
status = SecItemAdd((CFTypeRef)[NSDictionary dictionaryWithObjectsAndKeys:KEYCHAIN_ITEM_ATTRIBUTES, data, kSecValueData, nil], NULL);
NSLog(@"SecItemAdd status:%ld",status);
NSParameterAssert(status == errSecSuccess);
// get password
status = SecItemCopyMatching((CFTypeRef)[NSDictionary dictionaryWithObjectsAndKeys:KEYCHAIN_ITEM_ATTRIBUTES,
kSecMatchLimitOne, kSecMatchLimit, kCFBooleanTrue, kSecReturnData, nil], (CFTypeRef *)&data);
NSLog(@"SecItemCopyMatching status:%ld",status);
NSParameterAssert(status == errSecSuccess);
if (status == errSecItemNotFound)
NSLog(@"SecItemCopyMatching status:%ld", status);
else
NSLog(@"SecItemCopyMatching result:%@",[[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]);
}
关于 securityd 守护进程未启动,我可以检查它是否正在启动,使用
launchctl list | grep securityd
模拟器启动后,得到
- 0 com.apple.iPhoneSimulator:com.apple.securityd
我还尝试停止这个 securityd 守护进程并手动启动另一个守护进程...我查看了 GTM 的 RunIPhoneUnitTest.sh 脚本以获取我可以使用的简单行,但是当我尝试这个时
launchctl submit -l ios6securityd -- /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.0.sdk/usr/libexec/securityd
给我该守护进程的 -5 状态代码。