http://www.cnblogs.com/v2m_/archive/2012/01/18/2325782.html
说明:
每一个keyChain的组成如图,整体是一个字典结构.
1.kSecClass key 定义属于那一种类型的keyChain
2.不同的类型包含不同的Attributes,这些attributes定义了这个item的具体信息
3.每个item可以包含一个密码项来存储对应的密码
使用:
引入Security包,引入文件 #import <Security/Security.h>
添加
- (IBAction)add:(id)sender { if (nameField.text.length > 0 && passwordField.text.length > 0) { // 一个mutable字典结构存储item信息 NSMutableDictionary* dic = [NSMutableDictionary dictionary]; // 确定所属的类class [dic setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; // 设置其他属性attributes [dic setObject:nameField.text forKey:(id)kSecAttrAccount]; // 添加密码 secValue 注意是object 是 NSData [dic setObject:[passwordField.text dataUsingEncoding:NSUTF8StringEncoding] forKey:(id)kSecValueData]; // SecItemAdd OSStatus s = SecItemAdd((CFDictionaryRef)dic, NULL); NSLog(@"add : %ld",s); } }
查找
// 查找全部 - (IBAction)sel:(id)sender { NSDictionary* query = [NSDictionary dictionaryWithObjectsAndKeys:kSecClassGenericPassword,kSecClass, kSecMatchLimitAll,kSecMatchLimit, kCFBooleanTrue,kSecReturnAttributes,nil]; CFTypeRef result = nil; OSStatus s = SecItemCopyMatching((CFDictionaryRef)query, &result); NSLog(@"se;ect all : %ld",s); NSLog(@"%@",result); } // 按名称查找 - (IBAction)sname:(id)sender { if (nameField.text.length >0) { // 查找条件:1.class 2.attributes 3.search option NSDictionary* query = [NSDictionary dictionaryWithObjectsAndKeys:kSecClassGenericPassword,kSecClass, nameField.text,kSecAttrAccount, kCFBooleanTrue,kSecReturnAttributes,nil]; CFTypeRef result = nil; // 先找到一个item OSStatus s = SecItemCopyMatching((CFDictionaryRef)query, &result); NSLog(@"select name : %ld",s); // errSecItemNotFound 就是找不到 NSLog(@"%@",result); if (s == noErr) { // 继续查找item的secValue NSMutableDictionary* dic = [NSMutableDictionary dictionaryWithDictionary:result]; // 存储格式 [dic setObject:(id)kCFBooleanTrue forKey:kSecReturnData]; // 确定class [dic setObject:[query objectForKey:kSecClass] forKey:kSecClass]; NSData* data = nil; // 查找secValue if (SecItemCopyMatching((CFDictionaryRef)dic, (CFTypeRef*)&data) == noErr) { if (data.length) NSLog(@"%@",[[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]); } } } }
修改
- (IBAction)update:(id)sender { if (nameField.text.length >0 && passwordField.text.length > 0) { // 先查找看看有没有 NSDictionary* query = [NSDictionary dictionaryWithObjectsAndKeys:kSecClassGenericPassword,kSecClass, nameField.text,kSecAttrAccount, kCFBooleanTrue,kSecReturnAttributes,nil]; CFTypeRef result = nil; if (SecItemCopyMatching((CFDictionaryRef)query, &result) == noErr) { // 更新后的数据,基础是搜到的result NSMutableDictionary* update = [NSMutableDictionary dictionaryWithDictionary:(NSDictionary*)result]; // 修改要跟新的项 注意先加后删的class项 [update setObject:[query objectForKey:kSecClass] forKey:kSecClass]; [update setObject:[passwordField.text dataUsingEncoding:NSUTF8StringEncoding] forKey:kSecValueData]; [update removeObjectForKey:kSecClass]; #if TARGET_IPHONE_SIMULATOR // 模拟器的都有个默认的组“test”,删了,不然会出错 [update removeObjectForKey:(id)kSecAttrAccessGroup]; #endif // 得到要修改的item,根据result,但要添加class NSMutableDictionary* updateItem = [NSMutableDictionary dictionaryWithDictionary:result]; [updateItem setObject:[query objectForKey:(id)kSecClass] forKey:(id)kSecClass]; // SecItemUpdate OSStatus status = SecItemUpdate((CFDictionaryRef)updateItem, (CFDictionaryRef)update); NSLog(@"update:%ld",status);
删除
- (IBAction)del:(id)sender { if (nameField.text.length >0) { // 删除的条件 NSDictionary* query = [NSDictionary dictionaryWithObjectsAndKeys:kSecClassGenericPassword,kSecClass, nameField.text,kSecAttrAccount,nil]; // SecItemDelete OSStatus status = SecItemDelete((CFDictionaryRef)query); NSLog(@"delete:%ld",status); // // errSecItemNotFound 就是没有 } }
注意:
1.区别(标识)一个item要用kSecAttrAccount和kSecAttrService