UUID 浅析

在2013年3月21日苹果已经通知开发者,从2013年5月1日起,访问UIDID的应用将再也不能经过审核,替代的方案是开发者应该使用“在iOS 6中介绍的Vendor或Advertising标示符”。php


unique Identifier即将退出,苹果给了咱们Vendor和Advertising identifier两个选择,但应该用哪个?文档并无给出确切答案,具体使用哪一个彻底由你根据本身app的目的来决定。下面我将列出iOS中目前支持的,以及被废弃的惟一标示符方法,并对其作出相应的解释,但愿能够帮你作出正确的肯定。html

 

CFUUID
从iOS2.0开始,CFUUID就已经出现了。它是CoreFoundatio包的一部分,所以API属于C语言风格。CFUUIDCreate 方法用来建立CFUUIDRef,而且能够得到一个相应的NSString,以下代码:ios

CFUUIDRef cfuuid = CFUUIDCreate(kCFAllocatorDefault);NSString *cfuuidString = (NSString*)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, cfuuid));git

 

得到的这个CFUUID值系统并无存储。每次调用CFUUIDCreate,系统都会返回一个新的惟一标示符。若是你但愿存储这个标示符,那么须要本身将其存储到NSUserDefaults, Keychain, Pasteboard或其它地方。github

 

NSUUID
NSUUID在iOS 6中才出现,这跟CFUUID几乎彻底同样,只不过它是Objective-C接口。+ (id)UUID 是一个类方法,调用该方法能够得到一个UUID。经过下面的代码能够得到一个UUID字符串:服务器

NSString *uuid = [[NSUUID UUID] UUIDString];app

 

跟CFUUID同样,这个值系统也不会存储,每次调用的时候都会得到一个新的惟一标示符。若是要存储的话,你须要本身存储。在我读取NSUUID时,注意到获取到的这个值跟CFUUID彻底同样(不过也可能不同):框架

示例: 68753A44-4D6F-1226-9C60-0050E4C00067less

 

广告标示符(IDFA-identifierForIdentifier)
这是iOS 6中另一个新的方法,advertisingIdentifier是新框架AdSupport.framework的一部分。ASIdentifierManager单例提供了一个方法advertisingIdentifier,经过调用该方法会返回一个上面提到的NSUUID实例。ide

NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];

 

跟CFUUID和NSUUID不同,广告标示符是由系统存储着的。不过即便这是由系统存储的,可是有几种状况下,会从新生成广告标示符。若是用户彻底重置系统((设置程序 -> 通用 -> 还原 -> 还原位置与隐私) ,这个广告标示符会从新生成。另外若是用户明确的还原广告(设置程序-> 通用 -> 关于本机 -> 广告 -> 还原广告标示符) ,那么广告标示符也会从新生成。关于广告标示符的还原,有一点须要注意:若是程序在后台运行,此时用户“还原广告标示符”,而后再回到程序中,此时获取广告标示符并不会当即得到还原后的标示符。必需要终止程序,而后再从新启动程序,才能得到还原后的广告标示符。之因此会这样,我猜想是因为ASIdentifierManager是一个单例。


针对广告标示符用户有一个可控的开关“限制广告跟踪”。Nick Arnott的文章中已经指出了。将这个开关打开,实际上什么也没有作,不过这是但愿限制你访问广告标示符。这个开关是一个简单的boolean标志,当将广告标示符发到任意的服务器端时,你最好判断一下这个值,而后再作决定。

示例: 1E2DFA89-496A-47FD-9941-DF1FC4E6484A

 

Vindor标示符 (IDFV-identifierForVendor)
这种叫法也是在iOS 6中新增的,不过获取这个IDFV的新方法被添加在已有的UIDevice类中。跟advertisingIdentifier同样,该方法返回的是一个NSUUID对象。

NSString *idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString];

 

苹果官方的文档中对identifierForVendor有以下这样的一段描述 :

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.

 

若是知足这样的条件,那么获取到的这个属性值就不会变:相同的一个程序里面-相同的vindor-相同的设备。若是是这样的状况,那么这个值是不会相同的:相同的程序-相同的设备-不一样的vindor,或者是相同的程序-不一样的设备-不管是否相同的vindor。

 

看完上面的内容,我有这样的一个疑问“vendor是什么”。我首先想到的是苹果开发者帐号。但事实证实这是错误的。接着我想多是有一个AppIdentifierPrefix东西,跟钥匙串访问同样,能够在多个程序间共享。一样,这个想法也是的。最后证实,vendor很是简单:一个Vendor是CFBundleIdentifier(反转DNS格式)的前两部分。例如,com.doubleencore.app1 和 com.doubleencore.app2 获得的identifierForVendor是相同的,由于它们的CFBundleIdentifier 前两部分是相同的。不过这样得到的identifierForVendor则彻底不一样:com.massivelyoverrated 或 net.doubleencore。

 

在这里,还须要注意的一点就是:若是用户卸载了同一个vendor对应的全部程序,而后在从新安装同一个vendor提供的程序,此时identifierForVendor会被重置。

示例: 599F9C00-92DC-4B5C-9464-7971F01F8370


UDID
在以前的版本中是可用的,可是在iOS5以及以后的版本中,以及被弃用了。虽然,这个UDID用得很普遍,可是,不得不说的是,它在慢慢的远离开发者,不能在考虑使用UDID了。至于这个标示符是转为私有方法,或者彻底从之后的iOS版本中移除,还有待观察。不过,这个UDID在部署企业级签名程序时,很是方便。获取UDID的方法以下:

NSString *udid = [[UIDevice currentDevice] uniqueIdentifier];

示例: bb4d786633053a0b9c0da20d54ea7e38e8776da4

 

OpenUDID
在iOS 5发布时,uniqueIdentifier被弃用了,这引发了广大开发者须要寻找一个能够替代UDID,而且不受苹果控制的方案。由此OpenUDID成为了当时使用最普遍的开源UDID替代方案。OpenUDID在工程中实现起来很是简单,而且还支持一系列的广告提供商。

NSString *openUDID = [OpenUDID value];

 

OpenUDID利用了一个很是巧妙的方法在不一样程序间存储标示符 — 在粘贴板中用了一个特殊的名称来存储标示符。经过这种方法,别的程序(一样使用了OpenUDID)知道去什么地方获取已经生成的标示符(而不用再生成一个新的)。

 

以前已经提到过,在未来,苹果将开始强制使用advertisingIdentifier 或identifierForVendor。若是这一天到来的话,即便OpenUDID看起来是很是不错的选择,可是你可能不得不过渡到苹果推出的方法。

示例: 0d943976b24c85900c764dd9f75ce054dc5986ff

 

总结
但愿上面的信息可以帮助你在程序使用选择正确的惟一标示符。在这里,我建立了一个小的惟一标示符测试程序,你能够运行该程序,并查看一下显示的内容(包括上面提到的全部标示符)。另外,下面有两个表,表中描述了两个内容:在iOS中的可用性,以及何时能够得到重置的标示符。



 * 程序必须重启才能看到改变的效果。

** 删除了全部相同vendor提供的程序,才能看到改变的值。

 

代码以下:

//内连,使用状况较多下使用,

 

static inline NSString * GetUUIDString()

{

    CFUUIDRef  uuidObj = CFUUIDCreate(nil);

    NSString  *uuidString = (__bridge_transfer NSString*)CFUUIDCreateString(nil, uuidObj);

    CFRelease(uuidObj);

    return uuidString;

}

 

 

//类方法,建议新建NSString的分类使用,

 

+ (NSString*) getUUIDString

{

    CFUUIDRef  uuidObj = CFUUIDCreate(nil);

    NSString  *uuidString = (__bridge_transfer NSString*)CFUUIDCreateString(nil, uuidObj);

    CFRelease(uuidObj);

    return uuidString;

}

 

 

参考连接:

1.http://www.jianshu.com/p/47e6cbc34d85

2.http://hulefei29.iteye.com/blog/1862306

3.http://blog.csdn.net/shouqiangwei/article/details/42239765

相关文章
相关标签/搜索