开发者能拿到的标识符

iOS中目前支持的,以及被废弃的唯一标识符方法,并对其做出相应的解释.

CFUUID

  • 简介:从iOS2.0开始,CFUUID就已经出现了.它是CoreFoundatio包的一部分,因此API属于C语言风格.

  • 获取方法: CFUUIDCreate方法用来创建CFUUIDRef,并且可以获得一个相应的NSString.

CFUUIDRef cfuuid = CFUUIDCreate(kCFAllocatorDefault);
NSString *cfuuidString = (NSString*)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, cfuuid));
  • 获得的这个CFUUID值系统并没有存储.每次调用CFUUIDCreate,系统都会返回一个新的唯一标示符.如果你希望存储这个标示符,那么需要自己将其存储到NSUserDefaults, Keychain, Pasteboard或其它地方.

NSUUID

  • 简介:跟CFUUID一样,这个值系统也不会存储,每次调用的时候都会获得一个新的唯一标示符.如果要存储的话,需要自己存储.

  • 获取方法:

NSString *uuid = [[NSUUID UUID] UUIDString];
  • iOS 6 添加.NSUUID在iOS 6中才出现,这跟CFUUID几乎完全一样,只不过它是Objective-C接口.

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

广告标示符(IDFA-identifierForIdentifier)

  • 简介:广告标示符,由系统存储.适用于对外:例如广告推广,换量等跨应用的用户追踪等。但如果用户完全重置系统(还原位置与隐私)或者还原广告(还原广告标示符),这个广告标示符会重新生成,由于IDFA会出现取不到的情况,故绝不可以作为业务分析的主id,来识别用户。

  • iOS 6中新增,advertisingIdentifier是新框架AdSupport.framework的一部分.

  • 获取方法 ASIdentifierManager单例提供了一个方法advertisingIdentifier,通过调用该方法会返回一个上面提到的NSUUID实例.

NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
  • 注意:

    如果程序在后台运行,此时用户“还原广告标示符”,然后再回到程序中,此时获取广 告标示符并不会立即获得还原后的标示符。必须要终止程序,然后再重新启动程序,才能获得还原后的广告标示符。在同一个设备上的所有App都会取到相同的值,是苹果专门给各广告提供商用来追踪用户而设的,用户可以在 设置 -> 隐私 -> 广告追踪 里重置此id的值,或限制此id的使用。

针对广告标示符用户有一个可控的开关“限制广告跟踪”.将这个开关打开,实际上什么也没有做,不过这是希望限制你访问广告标示符.这个开关是一个简单的boolean标志,当将广告标示符发到任意的服务器端时,你最好判断一下这个值,然后再做决定.

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

Vindor标示符 (IDFV-identifierForVendor)

  • 简介:iOS 6.0系统新增用于替换uniqueIdentifier的接口。是给Vendor标识用户用的,每个设备在所属同一个Vender的应用里,都有相同的值。其中的Vender是指应用提供商,但准确点说,是通过BundleID的DNS反转的前两部分进行匹配,如果相同就是同一个Vender,例如对于com.somecompany.appone, com.somecompany.apptwo这两个BundleID来说,就属于同一个Vender,共享同一个idfv的值。和idfa不同的是,idfv的值是一定能取到的,所以非常适合于作为内部用户行为分析的主id,来标识用户,替代OpenUDID。如果用户将属于此Vender的所有App卸载,则idfv的值会被重置,即再重装此Vender的App,idfv的值和之前不同。

  • 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非常简单:一个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

  • 简介:UDID的全称是Unique Device Identifier,顾名思义,它就是苹果IOS设备的唯一识别码,它由40个字符的字母和数字组成。在很多需要限制一台设备一个账号的应用中经常会用到。在iOS5中可以获取到设备的UDID,iOS7中已经完全的禁用了它。iOS7之前的使用了的app如果在iOS7上运行,它不会返回设备的UDID,而是会返回一串字符串,以FFFFFFFF开头,跟着identifierForVendor的十六进制值。

  • iOS5起被废弃.UDID在部署企业级签名程序时可以使用.

  • 获取方法:

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

废弃以后 获取UUID方法: 私有API(不能在审核项目中使用!):AADeviceInfo.在项目中将真机上的AppleAccount.framework框架导出,引入Xcode工程中,利用runtime或者直接使用该类就行。(细节补充:导出AppleAccount.framework后,进入AppleAccount.framework的根目录,新建Headers文件夹,然后将dump出的头文件放在Headers目录,就可以像引用第三方framework一样在项目中使用)

  • 示例: bb4d786633053a0b9c0da20d54ea7e38e8776da4

OpenUDID

  • 简介:在iOS 5发布时,UDID被弃用了,由此OpenUDID成为了当时使用最广泛的替代UDID,且不受苹果控制的方案.OpenUDID在工程中实现起来非常简单,并且还支持一系列的广告提供商.

NSString *openUDID = [OpenUDID value];
  • OpenUDID利用了一个非常巧妙的方法在不同程序间存储标示符 — 在粘贴板中用了一个特殊的名称来存储标示符.通过这种方法,别的程序(同样使用了OpenUDID)知道去什么地方获取已经生成的标示符(而不用再生成一个新的). 但是由于iOS7开始对剪切板限制.同一个设备上应用间,无法再共享一个OpenUDID,OpenUDID作为设备唯一标识的能力被大大削弱.

  • 注意事项 每台iOS设备的OpenUDID是通过第一个带有OpenUDID SDK包的App生成,如果你完全删除全部带有OpenUDID SDK包的App(比如恢复系统等),那么OpenUDID会重新生成,而且和之前的值会不同,相当于新设备.

  • 示例: 0d943976b24c85900c764dd9f75ce054dc5986ff

MAC地址

  • 简介:MAC地址在网络上用来区分设备的唯一性,接入网络的设备都有一个MAC地址,他们肯定都是不同的,是唯一的。一部iPhone上可能有多个MAC地址,包括WIFI的、SIM的等,但是iTouch和iPad上就有一个WIFI的,因此只需获取WIFI的MAC地址就好了,也就是en0的地址。MAC地址就如同我们身份证上的身份证号码,具有全球唯一性。但在iOS7之后,如果请求Mac地址都会返回一个固定值。

  • iOS7.0起废弃

  • 获取方法

- (NSString *)macAddress
{
int mib[6];
size_t len;
char *buf;
unsigned char *ptr;
struct if_msghdr *ifm;
struct sockaddr_dl *sdl;
mib[0] = CTL_NET;
mib[1] = AF_ROUTE;
mib[2] = 0;
mib[3] = AF_LINK;
mib[4] = NET_RT_IFLIST;
if ((mib[5] = if_nametoindex("en0")) == 0) {
printf("Error: if_nametoindex error/n");
return NULL;
}
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
printf("Error: sysctl, take 1/n");
return NULL;
}
if ((buf = malloc(len)) == NULL) {
printf("Could not allocate memory. error!/n");
return NULL;
}
if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
printf("Error: sysctl, take 2");
return NULL;
}
ifm = (struct if_msghdr *)buf;
sdl = (struct sockaddr_dl *)(ifm + 1);
ptr = (unsigned char *)LLADDR(sdl);
NSString *outstring = [NSString stringWithFormat:@"%02x:%02x:%02x:%02x:%02x:%02x", *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];
NSLog(@"outString:%@", outstring);
free(buf);
return [outstring uppercaseString];
}

iOS7以后 建议使用标示符

IDFA: 适用于对外:例如广告推广,换量等跨应用的用户追踪等 IDFV: 适用于对内:例如分析用户在应用内的行为等