iOS唯一标志符的选择方案
首先要明白唯一标志符的是什么,它是我们唯一标记该设备的一串字符串,它可以是不变的(如系统的mac地址),也可以是变化的(相对于系统来说,应用程序是可能被用户删除的,例如idfv广告标志符),虽然IDFV可能会被删除,但是我们仍然可以选择把它存在系统钥匙串里,作为我们的唯一标志符。
idfa的劣势是可能取不到,也可能被改变。下面介绍下唯一标志符的的各路诸侯。
1.UDID -iOS5时代的产物
最早的唯一标志符应该就是UDID。UDID的全称是Unique Device Identifier,顾名思义,即苹果iOS设备的唯一识别码,它由40个字符的字母和数字组成。在很多需要限制一台设备一个账号的应用中经常会用到。在iOS5中可以获取到设备的UDID,后来被苹果禁止。
2.IDFA广告标志符适用于对外的广告追踪,跨应用间的倒量追踪。
#import <AdSupport/AdSupport.h>
NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
通过调用该方法会返回一个NSUUID实例,最后可以获得一个UUID,由系统存储着的。不过即使这是由系统存储的,但是有几种情况下,会重新生成广告标示符。如果用户完全重置系统((设置程序 -> 隐私 -> 广告 -> 还原广告标志符) ,这个广告标示符会重新生成。另外在iOS10以后如果用户明确的限制广告追踪(设置-> 隐私 -> 广告 -> 限制广告追踪) ,那么广告标示符只能获取到一串无意义的0。
3 Mac地址 被弃用,iOS7以后开发者只能获取到固定地址:02:00:00:00:00:00。
In iOS 7 and later, if you ask for the MAC address of an iOS device, the system returns the value 02:00:00:00:00:00. If you need to identify the device, use the identifierForVendor property of UIDevice instead. (Apps that need an identifier for their own advertising purposes should consider using the advertisingIdentifier property of ASIdentifierManager instead.)
从iOS7及更高版本往后,苹果建议使用 ASIdentifierManager的advertisingIdentifier属性作为替代)
4IDFV-Vindor标示符,适用于对内:例如分析用户在应用内的行为等。
如果用户将属于此Vender的所有App卸载,则idfv的值会被重置,即再重装此Vender的App,idfv的值和之前不同。
因此我们使用idfv+keychain存储第一次获取的IDFV可以保证程序卸载重装,IDFV不变。
相比卸载重装,IDFA还是较稳定的,但是用IDFA在送审的时候,要表明用了广告标识符,并且要导入依赖库,为了不引起必要麻烦,本人采用了IDFV+keychain的方法
注意:每个设备在所属同一个Vender的应用里,都有相同的值。其中的Vender是指应用提供商,但准确点说,是通过BundleID的DNS反转的前两部分进行匹配,如果相同就是同一个Vender,例如对于com.somecompany.app1,com.somecompany.app2
这两个BundleID来说,就属于同一个Vender,共享同一个idfv的值。和idfa不同的是,idfv的值是一定能取到的,所以非常适合于作为内部用户行为分析的主id,来标识用户,替代OpenUDID。
5.UUID
UUID是Universally Unique Identifier的缩写,中文意思是通用唯一识别码。它是让分布式系统中的所有元素,都能有唯一的辨识资讯,而不需要透过中央控制端来做辨识资讯的指定。这样,每个人都可以建立不与其它人冲突的 UUID。在此情况下,就不需考虑数据库建立时的名称重复问题。苹果公司建议使用UUID为应用生成唯一标识字符串。
开发者可以在应用第一次启动时调用一 次,然后将该串存储起来,替代UDID来使用。但是,如果用户删除该应用再次安装时,又会生成新的字符串,所以不能保证唯一识别该设备。使用UUID,就要考虑应用被删除后再重新安装时的处理。一个解决的办法是:UUID一般只生成一次,保存在iOS系统里面,如果应用删除了,重装应用之后它的UUID还是一样的,除非系统重置 。但是不能保证在以后的系统升级后还能用(如果系统保存了该信息就能用)。
UDID被弃用,使用UUID来作为设备的唯一标识。获取到UUID后,如果用NSUserDefaults存储,当程序被卸载后重装时,再获得的UUID和之前就不同了。使用keychain存储可以保证。程序卸载重装时,UUID不变。(但是升级系统后,UUID还是会改变的)
最后:推荐方案UUID+SSKeyChain
在第一次启动后把系统生成的UUID保存到钥匙串中,这样一来即使iOS系统升级UUID发生改变,但是钥匙串保存的UUID不会改变,因为钥匙串是系统级存储系统,它不会随着系统的升级而消失,这也是为什么推荐的理由。
推荐使用钥匙串库:https://github.com/Mingriweiji-github/sskeychain-master,如果报错,修改如下。
//#import <SSKeychain/SSKeychainQuery.h>
#import "SSKeychainQuery.h"
实践是检验真理的唯一标准
1.检验第一步:
15:11:09.393029+0800 SSKeyChainDemo[2927:896104] 第一次获取的UUID :644C445D-5F8D-4117-92D2-F3BF826C1963
2.检验第二步:删除APP
3.检验第三步:
15:17:14.680873+0800 SSKeyChainDemo[2938:898470] 获取的UUID :644C445D-5F8D-4117-92D2-F3BF826C1963
可以看到即使删除App,重新安装UUID仍然没有改变。
最后Github附上
demo地址,如有问题,请留言。