UUID iOS设备唯一标示符
2015-08-30 14:16
387 查看
1.已禁用-[UIDevice uniqueIdentifier] 苹果总是把用户的隐私看的很重要。-[UIDevice uniqueIdentifier]在iOS5实际在iOS5的时候已经被遗弃了,但是iOS7中已经完全的禁用了它。Xcode5甚至不会允许你编译包含了指引到-[UIDevice uniqueIdentifier]的app。此外,iOS7之前的使用了-[UIDevice uniqueIdentifier] 的app如果在iOS7上运行,它不会返回设备的UUID,而是会返回一串字符串,以FFFFFFFF开头,跟着-[UIDevice identifierForVendor]的十六进制值。 2.MAC地址不能再用来设别设备 还有一个生成iOS设备唯一标示符的方法是使用iOS设备的Media Access Control(MAC)地址。一个MAC地址是一个唯一的号码,它是物理网络层级方面分配给网络适配器的。这个地址苹果还有其他的名字,比如说是硬件地址(Hardware Address)或是Wifi地址,都是指同样的东西。 有很多工程和框架都使用这个方法来生成唯一的设备ID。比如说ODIN。然而,苹果并不希望有人通过MAC地址来分辨用户,所以如果你在iOS7系统上查询MAC地址,它现在只会返回02:00:00:00:00:00。 3.现在苹果明确的表明你应该使用-[UIDevice identifierForVendor]或是-[ASIdentifierManager advertisingIdentifier]来作为你框架和应用的唯一标示符。坦白的来说,应对这些变化也不是那么的难,见以下代码片段:
<pre name="code" class="objc">NSString *identifierForVendor = [[UIDevice currentDevice].identifierForVendor UUIDString]; NSString *identifierForAdvertising = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString];每种方法都适配一种特别的用法: identifierForVendor对供应商来说是唯一的一个值,也就是说,由同一个公司发行的的app在相同的设备上运行的时候都会有这个相同的标识符。然而,如果用户删除了这个供应商的app然后再重新安装的话,这个标识符就会不一致。 advertisingIdentifier会返回给在这个设备上所有软件供应商相同的 一个值,所以只能在广告的时候使用。这个值会因为很多情况而有所变化,比如说用户初始化设备的时候便会改变。
4.由于identifierForVendor删除了这个供应商的app然后再重新安装的话,这个标识符就会不一致,所以要解决这个问题可以把第一次生成的唯一标示符,保存到keyChain中,当应用被删除后keyChain中的数据还在,下次在从keyChain中取就OK了
废话就讲到这了,下面是代码:
可以把下面代码直接拷贝去用,改下你的类名就ok了
#define KEY_UDID @"KEY_UDID" #define KEY_IN_KEYCHAIN @"KEY_IN_KEYCHAIN" #import <Security/Security.h> #import "APPIdentificationManage.h" @implementation APPIdentificationManage singleton_implementation(APPIdentificationManage) #pragma mark 获取UUID /** *此uuid在相同的一个程序里面-相同的vindor-相同的设备下是不会改变的 *此uuid是唯一的,但应用删除再重新安装后会变化,采取的措施是:只获取一次保存在钥匙串中,之后就从钥匙串中获取 **/ - (NSString *)openUDID { NSString *identifierForVendor = [[UIDevice currentDevice].identifierForVendor UUIDString]; return identifierForVendor; } #pragma mark 保存UUID到钥匙串 - (void)saveUDID:(NSString *)udid { NSMutableDictionary *udidKVPairs = [NSMutableDictionary dictionary]; [udidKVPairs setObject:udid forKey:KEY_UDID]; [[APPIdentificationManage sharedAPPIdentificationManage] save:KEY_IN_KEYCHAIN data:udidKVPairs]; } #pragma mark 读取UUID /** *先从内存中获取uuid,如果没有再从钥匙串中获取,如果还没有就生成一个新的uuid,并保存到钥匙串中供以后使用 **/ - (id)readUDID { if (_uuid == nil || _uuid.length == 0) { NSMutableDictionary *udidKVPairs = (NSMutableDictionary *)[[APPIdentificationManage sharedAPPIdentificationManage] load:KEY_IN_KEYCHAIN]; NSString *uuid = [udidKVPairs objectForKey:KEY_UDID]; if (uuid == nil || uuid.length == 0) { uuid = [self openUDID]; [self saveUDID:uuid]; } _uuid = uuid; } return _uuid; } #pragma mark 删除UUID - (void)deleteUUID { [APPIdentificationManage delete:KEY_IN_KEYCHAIN]; } #pragma mark 查询钥匙串 - (NSMutableDictionary *)getKeychainQuery:(NSString *)service { return [NSMutableDictionary dictionaryWithObjectsAndKeys: (__bridge_transfer id)kSecClassGenericPassword,(__bridge_transfer id)kSecClass, service, (__bridge_transfer id)kSecAttrService, service, (__bridge_transfer id)kSecAttrAccount, (__bridge_transfer id)kSecAttrAccessibleAfterFirstUnlock,(__bridge_transfer id)kSecAttrAccessible, nil]; } #pragma mark 将数据保存到钥匙串 - (void)save:(NSString *)service data:(id)data { NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery); [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge_transfer id)kSecValueData]; SecItemAdd((__bridge_retained CFDictionaryRef)keychainQuery, NULL); } #pragma mark 加载钥匙串中数据 - (id)load:(NSString *)service { id ret = nil; NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge_transfer id)kSecReturnData]; [keychainQuery setObject:(__bridge_transfer id)kSecMatchLimitOne forKey:(__bridge_transfer id)kSecMatchLimit]; CFDataRef keyData = NULL; if (SecItemCopyMatching((__bridge_retained CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) { @try { ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge_transfer NSData *)keyData]; } @catch (NSException *e) { NSLog(@"Unarchive of %@ failed: %@", service, e); } @finally { } } return ret; } #pragma mark 删除钥匙串中数据 - (void)delete:(NSString *)service { NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery); } @end
相关文章推荐
- STL源码剖析 [容器](六)[stl_queue.h]
- [算法] Quick Sort
- iOS开发笔记1-UINavigationController
- UVa 1608:Non-boring swquences(分治)
- CEGUI编译
- EasyUI常用控件禁用方法
- UIimage View
- UIButton状态:添加图片:
- 剖析安卓build系统的设计思想以及案例模拟
- iphone开发之表格组件UITableView的使用(二)如何分组展示数据并添加组头和组尾描述
- easyui使用mergeCells合并单元格后第一行行高过大
- iOS开发 - UIAlertController 弹框提醒
- 考评系统学到的UI设计理念
- UIWindow和UIView
- UI设计规范
- iOS8新特性(2)——UIPopoverController和UIPresentationController
- iOS8新特性(1)——UIAlertController
- 编写广播时出现Exported receiver does not require permission
- 学习YUI.Ext 第一天:EXT简介(一)
- HOWTO: Install, Build and Use openCV (MacOSX 10.10)