利用KeyChain保存、获取设备唯一识别UUID
一、需要导入Security.framework

二、填写bundle id

二、Target - Capabilities - Keychain Sharing -ON

注意这个Keychain Sharing和上述bundle id的数值应该是一样的。
此时左侧目录会自动生成Entitlements文件。

三、编写两个类
UUID类
.h文件
#import <Foundation/Foundation.h>
@interface UUID : NSObject
+(NSString *)getUUID;
@end
.m文件

以下为代码(就是把上面图片的代码赋值下来,方便拷贝)
#import "UUID.h"
#import "GSKey.h"
#define KEY_USERNAME_PASSWORD @"com.company.xueban.usernamepassword"
#define KEY_USERNAME @"com.company.xueban.username"
#define KEY_PASSWORD @"com.company.xueban.password"
@implementation UUID
+(NSString *)getUUID{
NSString * strUUID = (NSString *)[GSKey load:@"com.company.xueban.usernamepassword"];
//首次执行该方法时,uuid为空
if ([strUUID isEqualToString:@""] || !strUUID) {
//生成一个uuid的方法
CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
strUUID = (NSString *)CFBridgingRelease(CFUUIDCreateString (kCFAllocatorDefault,uuidRef));
//将该uuid保存到keychain
[GSKey save:KEY_USERNAME_PASSWORD data:strUUID];
}
return strUUID;
}
@end
GSKey类
.h文件

以下为代码:
#import <Foundation/Foundation.h>
@interface GSKey : NSObject
+ (void)save:(NSString *)service data:(id)data;
+ (id)load:(NSString *)service;
+ (void)deleteKeyData:(NSString *)service;
@end
.m文件

代码(用于复制)
#import "GSKey.h" #import "GSKey.h" //static NSString* const KEY_INKEYCHAIN_UUID =@"唯一识别的KEY_UUID"; //static NSString* const KEY_UUID =@"唯一识别的key_uuid"; @implementation GSKey + (NSMutableDictionary *)getKeychainQuery:(NSString *)service { return [NSMutableDictionary dictionaryWithObjectsAndKeys: (id)kSecClassGenericPassword,(id)kSecClass, service, (id)kSecAttrService, service, (id)kSecAttrAccount, (id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible, nil]; } + (void)save:(NSString *)service data:(id)data { //Get search dictionary NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; //Delete old item before add new item SecItemDelete((CFDictionaryRef)keychainQuery); //Add new object to search dictionary(Attention:the data format) [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data requiringSecureCoding:false error:nil] forKey:(id)kSecValueData]; //Add item to keychain with the search dictionary SecItemAdd((CFDictionaryRef)keychainQuery, NULL); } + (id)load:(NSString *)service { id ret = nil; NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; //Configure the search setting //Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue [keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; [keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; CFDataRef keyData = NULL; if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) { @try { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData]; #pragma clang diagnostic pop //ret = [NSKeyedUnarchiver unarchivedObjectOfClass:(__bridge NSData *)keyData fromData:(__bridge NSData *)keyData error:nil]; } @catch (NSException *e) { NSLog(@"Unarchive of %@ failed: %@", service, e); } @finally { } } if (keyData) CFRelease(keyData); return ret; } + (void)deleteKeyData:(NSString *)service { NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; SecItemDelete((CFDictionaryRef)keychainQuery); } @end