//UUID
    NSLog(@"-=-=-=-=-=-=-=-==-=-==qqqqqqqqqqqqqqqqqqqqqqq:::::::::::%@", [[NSUUID UUID] UUIDString]);
    //Vindor标示符 (IDFV-identifierForVendor)
    NSLog(@"-=-=-=-=-=-=-=-==-=-==qqqqqqqqqqqqqqqqqqqqqqq:::::::::::%@", [[[UIDevice currentDevice] identifierForVendor] UUIDString]);
    //广告标示符(IDFA-identifierForIdentifier)
    NSLog(@"-=-=-=-=-=-=-=-==-=-==qqqqqqqqqqqqqqqqqqqqqqq:::::::::::%@", [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString]);

获取唯一UUID/UDID的方案

概述

如何保证获取到的UUID能够唯一标识每一台设备呢?我们知道通过UIDevice可以获取到UUIDString,但是如果App被删除了然后重新安装,就会得到不同的UUIDString,这并不是我们希望的。

那么,有什么办法可以解决这个问题呢?这里不说5.0之前的一切,只说6.0之后的如何做到。

下面提供的只是代码片段,不是完整的代码!

案例

苹果在iOS6.0版本之后,在UIDevice提供了以下属性:

@property(nullable, nonatomic,readonly,strong) NSUUID      *identifierForVendor

   

通过这个属性,就可以获取到UUID:

/* Return a string description of the UUID, such as "E621E1F8-C36C-495A-93FC-0C247A3E6E5F" */
@property (readonly, copy) NSString *UUIDString;
   

我们来操作一下,先运行某个App,然后打印UUIDString:

B907009B-8C63-4CA8-B3FB-B2724AE96DD5

   

然后删除掉这个App,再重新安装,然后再打印:

B907009B-8C63-4CA8-B3FB-B2724AE96DD5

   

为什么是一样的呢?不是说会变吗?是的,因为手机上还安装了其它跟这个App同属于同一开发商的App。现在,我们把所有与它是同一开发商的App全部删除,再重新安装,再打印如下:

1A73D3A3-3CD6-4655-8566-042FE7C8B2AC

   

果然发生了变化了。

官方文档

苹果官方文档这么说的

The value of this property is the same for apps that come from the same vendor running on the same device. A different value is returned for apps on the same device that come from different vendors, and for apps on different devices regardless of vendor.

The value of this property may be nil if the app is running in the background, before the user has unlocked the device the first time after the device has been restarted. If the value is nil, wait and get the value again later.

The value in this property remains the same while the app (or another app from the same vendor) is installed on the iOS device. The value changes when the user deletes all of that vendor’s apps from the device and subsequently reinstalls one or more of them. Therefore, if your app stores the value of this property anywhere, you should gracefully handle situations where the identifier changes.

意思大概就是说

在同一设备上运行来源于同一开发商的App,获取到的UUIDString属性是同一个值。当在同一设备上运行来源于不同的开发商的App,所获取到的UUIDString是不同的。在不同的设备上,不管是否同属于同一个开发商,得到的UUIDString都会不同。

当设备重启后,若用户第一次未解锁设备,而app在后台运行时,这个UUIDString可能为nil。如果值为nil,请等待并在稍候重新获取。

当app或者另外来源于同一开发商的app被安装到同一设备上,这个UUIDString会保持一致(比如上面的小例子,打印出来就是一致的)。当 用户删除掉设备上所有同一开发商的app后,重新安装其中某一个app,这时候所获取到的UUIDString就会发生变化。因此,不管app存储将这个 UUID存储到哪里,你都应该手动处理这种改变。

那么如何解决这种改变呢?

解决方案

解决方案就是能所生成的UUIDString存储到KeyChain中,使用同一个access group、同一个identifier。每次获取UUID,都先从KeyChain中获取,若为空,则通过UIDevice获取UUIDString并 存储到KeyChaing,代码版本如下:

+ (NSString *)UUID {
    KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"HuangyibiaoAppID" accessGroup:@"com.huangyibiao.test.group"];
    NSString *UUID = [wrapper objectForKey:(__bridge id)kSecValueData];
    
    if (UUID.length == 0) {
      UUID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
      [wrapper setObject:UUID forKey:(__bridge id)kSecValueData];
    }
  
  return UUID;
}
 
ios 使用NSURLCredential 创建UDID

+ (NSString*)createUUIDString{

CFUUIDRef puuid = CFUUIDCreate( nil );

CFStringRef uuidString = CFUUIDCreateString( nil, puuid );

NSString * result = (NSString *)CFBridgingRelease(CFStringCreateCopy( NULL, uuidString));

CFRelease(puuid);

CFRelease(uuidString);

result = [result stringByReplacingOccurrencesOfString:@"-" withString:@""];

return result;

}

+ (NSURLProtectionSpace *)shareProtectionSpace{

static NSURLProtectionSpace* protectionSpace = nil;

static dispatch_once_t predicate;

dispatch_once(&predicate, ^{

NSURL *url = [NSURL URLWithString:@"http://www.sina.com"];

protectionSpace  = [[NSURLProtectionSpace alloc] initWithHost:url.host

port:[url.port integerValue]

protocol:url.scheme

realm:nil

authenticationMethod:NSURLAuthenticationMethodHTTPDigest];

});

return protectionSpace;

}

+ (NSString *)getUDID{

NSURLProtectionSpace* protectionSpace = [self shareProtectionSpace];

NSDictionary *credentials = [[NSURLCredentialStorage sharedCredentialStorage] credentialsForProtectionSpace:protectionSpace];

NSURLCredential* credential = [credentials.objectEnumerator nextObject];

NSString* passwd = credential.password;

NSString* username = credential.user;

if (passwd && passwd.length > 0) {

return passwd;

}else{

NSString* udid = [self createUUIDString];

credential = [NSURLCredential credentialWithUser:@"sina" password:udid persistence:NSURLCredentialPersistencePermanent];

[[NSURLCredentialStorage sharedCredentialStorage] setCredential:credential forProtectionSpace:protectionSpace];

return udid;

}

}

iOS 设备标识的更多相关文章

  1. 浅谈移动端设备标识码:DeviceID、IMEI、IDFA、UDID和UUID

    ---恢复内容开始--- 转:https://www.jianshu.com/p/38f4d1a4763b [心路历程] 最近刚好在思考工作中统计数据所用的标识码产生的数据误差到底有多大,借此机会几番 ...

  2. 浅谈移动端设备标识码:DeviceID、IMEI、IDFA、UDID和UUID -费元星

    在公司做数据分析的时候,发现NA端有很多ID,所有来系统的理解一下,有问题大家多指出   [心路历程] 最近刚好在思考工作中统计数据所用的标识码产生的数据误差到底有多大,借此机会几番搜索资料+请教大神 ...

  3. [转]iOS设备唯一标识探讨

    转自:http://www.jianshu.com/p/b83b0240bd0e iOS设备唯一标识探讨 为了统计和检测应用的使用数据,几乎每家公司都有获取唯一标识的业务需求,在iOS5以前获取唯一标 ...

  4. iOS设备的标识---UUID和IDFA

    一:1.1 :UDID 简介:UDID的全称是Unique Device Identifier,顾名思义,它就是苹果IOS设备的唯一识别码,它由40个字符的字母和数字组成.在很多需要限制一台设备一个账 ...

  5. 获取iOS设备唯一标识

    [获取iOS设备唯一标识] 1.已禁用-[UIDevice uniqueIdentifier] 苹果总是把用户的隐私看的很重要.-[UIDevice uniqueIdentifier]在iOS5实际在 ...

  6. 有关 iOS 的开发证书、应用标识、设备标识、配置文件以及密钥 #DF

    iOS开发过程中如果需要进行真机调试.发布需要注册申请很多证书, 以下是对iOS开发的常用证书和密钥等的逐一简单说明: 证书 iOS常用的证书包括开发证书和发布证书,无论是真机调试还是最终发布应用到A ...

  7. 【转】iOS设备的UDID是什么?苹果为什么拒绝获取iOS设备UDID的应用?如何替代UDID?

    本文讲诉的主要是为什么苹果2011年8月发布iOS 5后就开始拒绝App获取设备的UDID以及UDID替补方案,特别提醒开发者苹果App Store禁止访问UDID的应用上架(相关推荐:APP被苹果A ...

  8. 如何唯一确定一台iOS设备

    如果你的iOS应用需要针对设备做特定的操作,或者需要硬件的信息来进行判定等等的,你就需要对iOS设备进行唯一性的判定. 苹果设备有个先天的东西符合这个需求,UDID,这个东东用iTunes就可以看到, ...

  9. 关于iOS设备的那些事

    首先推荐一个在用的库XYQuick 地址:https://github.com/uxyheaven/XYQuick idfa: 获取方式 [ASIdentifierManager sharedMana ...

随机推荐

  1. 在IBM Bluemix上部署Hyperledger应用

    简介 IBM Bluemix (http://www.ibm.com/bluemix‎)是一个基于cloud的应用开发和部署平台,提供包括多种服务和运行环境的支持.对Hyperledger应用开发者而 ...

  2. nodejs学习篇 (1)webstorm创建nodejs + express + jade 的web 项目

    之前简单了解过nodejs,觉得用nodejs来做个网站也太麻烦了,要自己拼html的字符串返回,这能做网站嘛? 最近看到使用jade模板来开发,觉得挺新奇的,于是试了一把,也了解了一些特性,算是个新 ...

  3. java中synchronized关键字的用法

    在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. j ...

  4. ASP.NET MVC使用SSI来实现页面静态化

    页面静态化分为两种:伪静态和真静态,这里主要介绍的是真静态. 进入正题之前先简单介绍一下SSI和shtml: 1).SSI是Server Side Include的简称(服务器端嵌入) 2).shtm ...

  5. 使用CKplayer插件在网页中嵌入视频的方法(常用笔记2)

    在做网站中有时候我们需要在网页中嵌入视频,一般视频嵌入有以下几种方法: 1. 优酷代码嵌入 优点:简单,方便,可靠. 缺点:有广告,现在的网站非常注重用户体验,如果打开一个在线视频是有长广告的一定会崩 ...

  6. EC笔记,第一部分:3.尽量使用const

    03.尽量使用const 1.const概述 2.返回const 为何要返回一个const? 因为如果不返回const,程序员可能写出fun(a,b)=c;这样的代码,也许是因为打字错误可能写出类似i ...

  7. XE8 FMX SpeedButton 大图标(改 Style)

    自从 XE8 提供 ImageList 带来了很多便利,但 SpeedButton 的图标太小(不够大气),还好 FMX 提供了 Style 可供使用者自订图标大小及显示位置,请自行按图索骥,做一遍: ...

  8. SNAT,是源地址转换,其作用是将ip数据包的源地址转换成另外一个地址

    SNAT,可能有人觉得奇怪,好好的为什么要进行ip地址转换啊,为了弄懂这个问题,我们要看一下局域网用户上公网的原理,假设内网主机A(192.168.2.8)要和外网主机B(61.132.62.131) ...

  9. 算法:冒泡排序(python版)

    1.将n个元素从大到小排序后,选择第k个大的元素 #!/usr/bin/env python #coding -*- utf:8 -*- #冒泡排序选第k个元素 import random impor ...

  10. 转:python signal信号

    转自:http://www.jb51.net/article/74844.htm 在liunx系统中要想每隔一分钟执行一个命令,最普遍的方法就是crontab了,如果不想使用crontab,经同事指点 ...