簡單的翻譯下,keychain能夠存儲密碼、證書等等,至於有什麼好處,呵呵噠,本身百度去吧,總結一點就是更安全,並且取的更方便吧,看app場景吧。安全
本次代碼,分爲兩段,一段爲保存代碼app
1 - (BOOL)saveData:(NSString *)str 2 { 3 OSStatus status = noErr; 4 NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; 5 [query setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; 6 /// query one 7 [query setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; 8 [query setObject:@"password" forKey:(id)kSecAttrService]; 9 CFMutableDictionaryRef outDicRef = nil; 10 status = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&outDicRef); 11 if(status==noErr) 12 { 13 NSLog(@"#######################query success"); 14 [query removeObjectForKey:(id)kSecMatchLimit]; 15 NSLog(@"=============code %d",SecItemDelete((CFDictionaryRef)query)); 16 NSMutableDictionary *dt = [[NSMutableDictionary alloc] init]; 17 [dt setObject:@"label" forKey:(id)kSecAttrLabel]; 18 [dt setObject:@"password" forKey:(id)kSecAttrService]; 19 [dt setObject:[str dataUsingEncoding:NSUTF8StringEncoding] forKey:(id)kSecValueData]; 20 [dt setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; 21 22 [dt setObject:@"Item label" forKey:(__bridge id)kSecAttrLabel]; 23 24 [dt setObject:@"Item description" forKey:(__bridge id)kSecAttrDescription]; 25 26 [dt setObject:@"Account" forKey:(__bridge id)kSecAttrAccount]; 27 28 [dt setObject:@"Service" forKey:(__bridge id)kSecAttrService]; 29 30 [dt setObject:@"Your comment here." forKey:(__bridge id)kSecAttrComment]; 31 status = SecItemAdd((CFDictionaryRef)dt, NULL); 32 if(status==noErr) 33 { 34 NSLog(@"#######################save success"); 35 return YES; 36 } 37 return YES; 38 } 39 else 40 if(status==errSecItemNotFound) 41 { 42 NSLog(@"#####################not found"); 43 //store 44 NSMutableDictionary *dt = [[NSMutableDictionary alloc] init]; 45 [dt setObject:@"label" forKey:(id)kSecAttrLabel]; 46 [dt setObject:@"password" forKey:(id)kSecAttrService]; 47 [dt setObject:[str dataUsingEncoding:NSUTF8StringEncoding] forKey:(id)kSecValueData]; 48 [dt setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; 49 50 [dt setObject:@"Item label" forKey:(__bridge id)kSecAttrLabel]; 51 52 [dt setObject:@"Item description" forKey:(__bridge id)kSecAttrDescription]; 53 54 [dt setObject:@"Account" forKey:(__bridge id)kSecAttrAccount]; 55 56 [dt setObject:@"Service" forKey:(__bridge id)kSecAttrService]; 57 58 [dt setObject:@"Your comment here." forKey:(__bridge id)kSecAttrComment]; 59 status = SecItemAdd((CFDictionaryRef)dt, NULL); 60 if(status==noErr) 61 { 62 NSLog(@"#######################save success"); 63 return YES; 64 } 65 if(outDicRef) 66 CFRelease(outDicRef); 67 return NO; 68 } 69 else 70 { 71 NSLog(@"########################error query %d",status); 72 } 73 return NO; 74 }
代碼有些凌亂,各位將就下吧,急着去睡覺~測試
讀取代碼以下:翻譯
1 - (NSString *)getData 2 { 3 OSStatus status = noErr; 4 NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; 5 [query setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; 6 /// query one 7 [query setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; 8 [query setObject:@"Service" forKey:(id)kSecAttrService]; 9 ///若是想取到相關屬性,這裏必須設置。就這個地方,害我搞半天 10 [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes]; 11 CFDictionaryRef attributes = nil; 12 ///取到屬性了 13 status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&attributes); 14 if(status==noErr) 15 { 16 NSLog(@"--------%@",attributes); 17 } 18 [query removeObjectForKey:(id)kSecReturnAttributes]; 19 CFDataRef outData; 20 ///取值,實際存放密碼的地方,這裏要設置 21 [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; 22 status = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&outData); 23 ///解析回來 24 NSString *str = [[NSString alloc] initWithData:(__bridge NSData *)outData encoding:NSUTF8StringEncoding]; 25 return str; 26 }
測試下:code
取到屬性:ip
取密碼rem