1 前言
今天是清明節(jié),全球都面臨著新冠病毒的威脅.有很多很多的勇士為了抗擊疫情,獻(xiàn)出了自己寶貴的生命.沒有歲月靜好,我們都需要全力以赴地前行.
作為程序員,我能做得就是認(rèn)真寫好每一個程序,我不懂如何消滅疫情,但是我需要消滅程序里的bug.
在很多情況下,我們希望能夠有一個設(shè)備標(biāo)識符來標(biāo)識一個設(shè)備.確保不同設(shè)備的標(biāo)識符是不同的,而同一臺設(shè)備的不同應(yīng)用之間,又能夠獲得到相同的標(biāo)識符.
我們很容易想到iOS的UDID本身就具有這個功能,但是在iOS5之后,蘋果出于信息安全方面的考慮,廢除了程序中獲取UDID的方式.
所以,我們需要用另一種方式來給設(shè)備頒發(fā)身份證.
我們逐個分析下,看看哪些是可行的.
1 UUID+KeyChain
什么是UUID?
UUID是Universally Unique Identifier通用唯一識別碼,是一種讓分布式系統(tǒng)中的所有元素读慎,都能有唯一的辨識信息的機制.
我們可以用UUID來作為設(shè)備的唯一標(biāo)識.
iOS中有兩種簡單的方式獲取UUID:
//方式一:
CFUUIDRef cfuuid = CFUUIDCreate(kCFAllocatorDefault);
NSString *cfuuidString = (NSString*)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, cfuuid));
//方式二:
NSString *uuid = [[NSUUID UUID] UUIDString];
生成UUID的方式很簡單,但是每次生成,都會得到不同的UUID.
我們需要在每次獲取時,首先在一個全局位置查詢是否存在,如果存在就直接返回,不存在才生成,并存儲到這個全局位置.
所以,這個全局的位置,是這種方案的關(guān)鍵.
設(shè)么是KeyChain?
KeyChain是iOS設(shè)備中的一個加密數(shù)據(jù)庫,用來存儲少量的用戶私密信息.
并且通過設(shè)置程序的訪問組,可以實現(xiàn)多個App之間共享數(shù)據(jù).
無疑KeyChain就是這個最理想的的全局位置.
所以UUID+KeyChain生成設(shè)備唯一標(biāo)識符的總體思路是:
- 1 為需要共享信息的App之間設(shè)置一個共享訪問組.
- 2 App獲取唯一標(biāo)識符時,首先從KeyChain中獲取,如果沒有,則新建并保存;如果有,則直接返回.
該方案,是創(chuàng)建設(shè)備唯一標(biāo)識符的最佳實踐,具體實現(xiàn),請單獨參考這篇文章:iOS | Uuid+KeyChain 我的設(shè)備性能不是最牛逼的,但他是全球唯一的
2 廣告標(biāo)識符Identifier For Advertising(IDFA)
IDFA是一個跟device相關(guān)的唯一標(biāo)識符咧党,主要用來廣告相關(guān)的業(yè)務(wù),每臺設(shè)備的IDFA是唯一的(模擬器獲取的廣告標(biāo)識符都是00000000-0000-0000-0000-000000000000,必須在真機上才能獲取到).
IDFA和應(yīng)用無關(guān),本設(shè)備上的任何App獲取到IDFA的內(nèi)容都是一致的.
獲取的方式也很簡單:
#import <AdSupport/AdSupport.h>
NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
IDFA在以下情況下會重新生成:
- 重置系統(tǒng),設(shè)置->通用->還原->還原位置與隱私
- 還原廣告標(biāo)識符,設(shè)置->通用->關(guān)于本機->廣告->還原廣告標(biāo)識符
如果認(rèn)可這兩種條件下的標(biāo)識符重置,其實獲取IDFA是用來標(biāo)識設(shè)備的最簡單有效的方法.
3 Push token
如果應(yīng)用中使用了推送功能,我們就會得到一個deviceToken.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken;
而這個deviceToken,就是一個設(shè)備唯一的值.也可以用來作為設(shè)備標(biāo)識.
但是這個方案有兩大缺點:
1,必須在有外網(wǎng)的情況下才能獲取到;
2,DeviceToken是保證唯一的,但是不確定會不會發(fā)生改變.從唯一值A(chǔ),變?yōu)槲ㄒ恢礏.
4 設(shè)備唯一標(biāo)識符Unique Device Identifier(UDID)
UDID是蘋果設(shè)備的唯一識別碼,在iOS 5以前可以直接用代碼獲取,獲取方式也很簡單:
NSString *udid = [[UIDevice currentDevice] uniqueIdentifier];
但是在iOS5以及之后,蘋果處于保護用戶隱私等原因,不再提供該方式讓開發(fā)者獲取設(shè)備的UDID
5 供應(yīng)商標(biāo)識符IdentifierForVendor(IDFV)
供應(yīng)商標(biāo)識符帮辟,是用來標(biāo)識應(yīng)用供應(yīng)商的.每個供應(yīng)商的所有應(yīng)用,都有相同的值嘲更。
如何判斷兩個應(yīng)用是否屬于同一個供應(yīng)商?
通過BundleID的反轉(zhuǎn)的前兩部分進(jìn)行匹配上沐,如果相同就是同一個供應(yīng)商.例如對于com.taobao.app1, com.taobao.app2 這兩個BundleID來說胯努,就屬于同一個供應(yīng)商纤勒,共享同一個IDFV的值坯苹。
它是iOS 6中新增的,跟advertisingIdentifier一樣摇天,該方法返回的是一個 NSUUID對象粹湃,可以獲得一個UUID。獲取方式也很簡單
NSString *strIDFV = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
但是如果用戶將屬于此供應(yīng)商的所有App卸載泉坐,則IDFV的值會被重置为鳄,即再重裝此供應(yīng)商的App,IDFV的值和之前不同腕让。
所以IDFV不適合用來作為設(shè)備的唯一標(biāo)識符.
6 Mac地址
什么是Mac地址?
每一個網(wǎng)卡都有一個唯一標(biāo)識符,叫做Mac地址.一部iPhone上有多個網(wǎng)卡,Wifi的網(wǎng)卡,流量的網(wǎng)卡等,所以會有多個Mac地址.但是每個Mac肯定是唯一的.
但是iOS7之后,獲取Mac地址蘋果也限制了開發(fā)者獲取Mac地址,所以這個方案也不行了.
總結(jié)
經(jīng)過上述分析,我們發(fā)現(xiàn):
- Mac地址,UDID的方式 已經(jīng)不被蘋果支持,無法實現(xiàn).
- IDFV,具有很大的局限性,也不提倡.
- PushToken的方案,客觀來說,有點離譜,非常不提倡.
- IDFA,如果能夠接受還原時標(biāo)識符的重置,其實是最簡單的方案.
- Uuid+KeyChain,這種方式才是最佳實踐,具體的實現(xiàn)方案,請參考:iOS | Uuid+KeyChain 讓你的設(shè)備全球唯一