iOS 獲取設備惟一標示符的方法

 

在開發中會遇到應用須要記錄設備標示,即便應用卸載後再安裝也可從新識別的狀況,在這寫一種實現方式——讀取設備的UUID(Universally Unique Identifier)並經過KeyChain記錄。html

首先iOS中獲取設備惟一標示符的方法一直隨版本的更新而變化。iOS 2.0版本之後UIDevice提供一個獲取設備惟一標識符的方法uniqueIdentifier,經過該方法咱們能夠獲取設備的序列號,這個也是目前爲止惟一能夠確認惟一的標示符。好景不長,由於該惟一標識符與手機一一對應,蘋果以爲可能會泄露用戶隱私,因此在 iOS 5.0以後該方法就被廢棄掉了;iOS 6.0系統新增了兩個用於替換uniqueIdentifier的接口,分別是:identifierForVendor,advertisingIdentifier,但這兩個接口會在應用從新安裝時改變數值,並非惟一的標示符,因此開發者改成使用WiFi的mac地址來取代;iOS 7中蘋果又封殺mac地址,因此開發者再次改變思路使用KeyChain來保存獲取到的UDID,這樣之後即便APP刪了再裝回來,也能夠從KeyChain中讀取回來。ios

首先保存設備的UUID,可使用類方法+ (id)UUID 是一個類方法,調用該方法能夠得到一個UUID。經過下面的代碼能夠得到一個UUID字符串:git

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

也能夠保存在iOS 6中新增的Vindor標示符 (IDFV-identifierForVendor),獲取這個IDFV的新方法被添加在已有的UIDevice類中。跟advertisingIdentifier同樣,該方法返回的是一個NSUUID對象。github

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

若是用戶卸載了同一個vendor對應的全部程序,而後在從新安裝同一個vendor提供的程序,此時identifierForVendor會被重置,因此這裏要用到KeyChain來保存。
KeyChain(鑰匙串)是使用蘋果設備常常使用的,一般要調試的話,都得安裝證書之類的,這些證書就是保存在KeyChain中,還有咱們平時瀏覽網頁記錄的帳號密碼也都是記錄在KeyChain中。iOS中的KeyChain相比OS X比較簡單,整個系統只有一個KeyChain,每一個程序均可以往KeyChain中記錄數據,並且只能讀取到本身程序記錄在KeyChain中的數據。iOS中Security.framework框架提供了四個主要的方法來操做KeyChain:安全

  • SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result);//查詢OSStatus
  • SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result); //添加OSStatus
  • SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate);//更新KeyChain中的ItemOSStatus
  • SecItemDelete(CFDictionaryRef query)//刪除KeyChain中的ItemOSStatus

這四個方法參數比較複雜,一旦傳錯就會致使操做KeyChain失敗,文檔中介紹的比較詳細,你們能夠查查官方文檔。而蘋果提供的KeyChain使用起來略麻煩,因此這裏推薦一個第三方庫SAMKeyChains.SAMKeyChains對蘋果安全框架API進行了簡單封裝,支持對存儲在鑰匙串中密碼、帳戶進行訪問,包括讀取、刪除和設置。SAMKeyChains使用簡單,經過實例代碼即可掌握。app

//保存一個UUID字符串到鑰匙串:
CFUUIDRef uuid = CFUUIDCreate(NULL);
assert(uuid != NULL);
CFStringRef uuidStr = CFUUIDCreateString(NULL, uuid);
 [SAMKeychain setPassword: [NSString stringWithFormat:@"%@", uuidStr]
 forService:@"com.yourapp.yourcompany"account:@"user"];
 
//從鑰匙串讀取UUID:
NSString *retrieveuuid = [SAMKeychain passwordForService:@"com.yourapp.yourcompany"account:@"user"];
 
**注意: setPassword和passwordForSevice方法中的**services 和 accounts 參數應該是一致的。

更多詳細用法說明能夠看SAMKeyChains Documentation框架

基本的實現思路即是這樣,下面是具體的一種具體實現代碼,僅供參考。ide

+ (NSString *)getDeviceId
{
    NSString * currentDeviceUUIDStr = [SAMKeychain passwordForService:@" "account:@"uuid"];
    if (currentDeviceUUIDStr == nil || [currentDeviceUUIDStr isEqualToString:@""])
    {
        NSUUID * currentDeviceUUID  = [UIDevice currentDevice].identifierForVendor;
        currentDeviceUUIDStr = currentDeviceUUID.UUIDString;
        currentDeviceUUIDStr = [currentDeviceUUIDStr stringByReplacingOccurrencesOfString:@"-" withString:@""];
        currentDeviceUUIDStr = [currentDeviceUUIDStr lowercaseString];
        [SAMKeychain setPassword: currentDeviceUUIDStr forService:@" "account:@"uuid"];
    }
    return currentDeviceUUIDStr;
}
相關文章
相關標籤/搜索