iOS UDID&&UUID
一、基本概念
- UDID
Unique Device Identifier :设备唯一标识符,用来唯一识别某台设备。在很多需要限制一台设备一个账号的应用中经常会用到,在Symbian时代,我们是使用IMEI作为设备的唯一标识的,可惜的是Apple官方不允许开发者获得设备的IMEI. - UUID
Universally Unique Identifier :通用唯一标识符,它能让你在不同地点,不借助中央服务器的情况下为任何项目创建唯一的标识符。例如:如果你要在App里加入一个永不会和其它ID冲突的用户ID,你可以自己建一个服务器,并用脚本为每个客户端分配一个ID。但这种集中管理的方式受网络影响,速度慢,而且服务器处理时间也影响速度。事实上你可以用UUID,它在每个客户端上生成ID,生成的ID不会跟任何ID重复(UUID生成条件:
1.当前日期和时间
2.时钟序列
3.全局唯一的IEEE机器识别号,如果有网卡从网卡MAC地址获得,没有网卡以其他方式获得)。
二、iOS中的使用
- UDID
[[UIDevice currentDevice] uniqueIdentifier]
iOS5.0之后,苹果为了保护用户隐私,取消了获取UDID的方法.
- UUID
//使用CFUUID生成UUID
CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef strRef = CFUUIDCreateString(kCFAllocatorDefault, uuidRef);
NSString *uuidString = [NSString stringWithString:(NSString*)strRef];
CFRelease(strRef);
CFRelease(uuidRef);
//使用NSUUID生成UUID
NSString *uuid = [NSUUID UUID].UUIDString;
- 测试几个UUID相关方法
for (int i = 0; i < 3; i++)
{
//返回当前的设备唯一标识UUID,该标识会随app卸载而更改
NSUUID *uuid = [UIDevice currentDevice].identifierForVendor;
NSLog(@"uuid 1 = %@",uuid.UUIDString);
}
NSLog(@"----------------------------------------------------");
for (int i = 0; i < 3; i++)
{
//随机生成一个UUID,每一个时刻的UUID值都不同
NSString *uuid = [NSUUID UUID].UUIDString;
NSLog(@"uuid 2 = %@",uuid);
}
NSLog(@"----------------------------------------------------");
for (int i = 0; i < 3; i++) {
//通过KeyChain+BoundleID+CFUUID生成的UUID,可用于设备识别,不会随设备删除APP而更改
NSLog(@"uuid 3 = %@", [UUID getUUID]);
}
/*
///打印结果
2018-07-13 09:52:24.019429+0800 UUID&UDID[939:297892] uuid 1 = D0F0DF48-AA92-4C59-915C-2B59C6FCD342
2018-07-13 09:52:24.019914+0800 UUID&UDID[939:297892] uuid 1 = D0F0DF48-AA92-4C59-915C-2B59C6FCD342
2018-07-13 09:52:24.020497+0800 UUID&UDID[939:297892] uuid 1 = D0F0DF48-AA92-4C59-915C-2B59C6FCD342
2018-07-13 09:52:24.020522+0800 UUID&UDID[939:297892] ----------------------------------------------------
2018-07-13 09:52:24.020544+0800 UUID&UDID[939:297892] uuid 2 = 24FFCCC0-736B-41BC-8057-B89E4D173040
2018-07-13 09:52:24.020560+0800 UUID&UDID[939:297892] uuid 2 = E9477585-5FDF-4CEB-99C4-F24CE23137A2
2018-07-13 09:52:24.020574+0800 UUID&UDID[939:297892] uuid 2 = 05E0B08F-9827-4D6B-B00F-8C8D087FC69B
2018-07-13 09:52:24.020605+0800 UUID&UDID[939:297892] ----------------------------------------------------
2018-07-13 09:52:24.025173+0800 UUID&UDID[939:297892] uuid 3 = 7B751FCB-5FA6-4A53-8268-626C10E7D879
2018-07-13 09:52:24.026516+0800 UUID&UDID[939:297892] uuid 3 = 7B751FCB-5FA6-4A53-8268-626C10E7D879
2018-07-13 09:52:24.027810+0800 UUID&UDID[939:297892] uuid 3 = 7B751FCB-5FA6-4A53-8268-626C10E7D879
*/
实现上面例子中的[UUID getUUID]方法,使用UUID替代UDID
这里需要实现2个工具类
KeyChainStore 和 UUIDKeyChainStore.h
#import <Foundation/Foundation.h> @interface KeyChainStore : NSObject + (void)save:(NSString *)service data:(id)data; + (id)load:(NSString *)service; + (void)deleteKeyData:(NSString *)service; @end
KeyChainStore.m
#import "KeyChainStore.h" @implementation KeyChainStore + (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{ //获取到查询字典 NSMutableDictionary *keychainQuery = [self getKeyChainQuery:service]; //添加新的item之前删除旧的 SecItemDelete((CFDictionaryRef)keychainQuery); //添加新的对象用来查询字典 [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData]; ; //将查询结果添加到keychain中 SecItemAdd((CFDictionaryRef)keychainQuery, NULL); } + (id)load:(NSString *)service{ id ret = nil; NSMutableDictionary *keychainQuery = [self getKeyChainQuery:service]; [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 { ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData]; } @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
UUID.h
#import <Foundation/Foundation.h> @interface UUID : NSObject + (NSString *)getUUID; @end
UUID.m
#import "UUID.h" #import "KeyChainStore.h" @implementation UUID + (NSString *)getUUID{ NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier]; NSString *strUUID = (NSString *)[KeyChainStore load:bundleID]; if ([strUUID isEqualToString:@""] || !strUUID) { CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault); strUUID = (NSString *)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuidRef)); [KeyChainStore save:bundleID data:strUUID]; } return strUUID; } @end