iOS獲取不變的UUID

什么是UUID? UUID「Universally Unique Identifier」通用唯一標(biāo)識符配深,是一個32位的十六進制序列,使用小橫線來連接:8-4-4-4-12。

在開發(fā)過程中妹懒,我們通常需要回去手機的唯一標(biāo)識符來區(qū)別不用的用戶,或者說需要將用戶的賬號與手機綁定双吆。如我們的項目需要一個賬號只能給一個人使用眨唬,所以我選擇使用賬號綁定手機,來盡量避免無法追蹤數(shù)據(jù)庫操作的操作人好乐,那么我們就需要獲取到手機的唯一標(biāo)識符在每次登陸賬號的時候傳給后臺作為登陸的限定條件之一匾竿。
??在 iOS 5 中, 可以獲取到系統(tǒng)的 UDID(Unique Device Identifier)蔚万,后來被 Apple 禁止了岭妖。
??在iOS 6 中,大家開始使用MAC地址 (Medium/Media Access Control),后來又被Apple禁止了。
??UDID和MAC地址被棄用昵慌,使用UUID來作為設(shè)備的唯一標(biāo)識苔巨。獲取到UUID后,如果NSUserDefaults存儲废离,當(dāng)程序被卸載后重裝時侄泽,再獲得的UUID和之前就不同了。使用keychain存儲可以保證程序卸載重裝時蜻韭,UUID不變悼尾。但當(dāng)刷機或者升級系統(tǒng)后,UUID還是會改變的肖方。
??那么讓我們來進行 UUID + keychain 獲取唯一標(biāo)識符的步驟:

1. 新建一個工程闺魏,看一下自己的Bundle Id.這個Bundle Id 要和你用真機測試時的證書上面的Bundle Id相匹配。
UUID_1.png
2. Target - Capabilities - Keychain Sharing - ON

這步主要目的是打開Keychain Sharing,將它由灰色狀態(tài)的OFF改為藍色狀態(tài)的ON俯画。
打開之后的變化如下:

UUID_2.png
UUID_3.png

左側(cè)的目錄會自動生成Entitlements文件析桥,不需要自己創(chuàng)建了。也就是說艰垂,Bundle Identifier泡仗、Keychain Sharing的Keychain Groups、Entitlements文件的Keychain Access Groups的第一個元素猜憎,它們要保持上圖所示的一致性娩怎。
設(shè)置好了以后可以運行下程序,沒問題可以進行下一步胰柑。

3. 傳說中的uuid類和keychain類來啦

既然蘋果的keychain方法會崩潰而且有些復(fù)雜截亦,我們只保存一個UUID的話可以用下面的簡單方法:

   UUID.h
   #import  尖括號(Foundation/Foundation.h)
   
   @interface UUID : NSObject
   
   +(NSString *)getUUID;
   
    
   @end
   
   UUID.m
   
   #import "UUID.h"
   #import "KeyChainStore.h"
   
   
   @implementation UUID
   
   +(NSString *)getUUID
   {
       NSString * strUUID = (NSString *)[KeyChainStore load:@"com.company.app.usernamepassword"];
       
       //首次執(zhí)行該方法時,uuid為空
       if ([strUUID isEqualToString:@""] || !strUUID)
       {
           //生成一個uuid的方法
           CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
           
           strUUID = (NSString *)CFBridgingRelease(CFUUIDCreateString (kCFAllocatorDefault,uuidRef));
      
           //將該uuid保存到keychain
           [KeyChainStore save:KEY_USERNAME_PASSWORD data:strUUID];
           
       }
       return strUUID;
   }
    
   @end
   
   KeyChainStore.h
   
   #import 尖括號(Foundation/Foundation.h)
   
   @interface KeyChainStore : NSObject
   
   + (void)save:(NSString *)service data:(id)data;
   + (id)load:(NSString *)service;
   + (void)deleteKeyData:(NSString *)service;
    
   @end
   
   KeyChainStore.m
   #import "KeyChainStore.h"
   
   
   @implementation KeyChainStore
   
   + (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
       return [NSMutableDictionary dictionaryWithObjectsAndKeys:
               (id)kSecClassGenericPassword,(id)kSecClass,
               service, (id)kSecAttrService,
               service, (id)kSecAttrAccount,
               (id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,
               nil];
   }
   
   + (void)save:(NSString *)service data:(id)data {
       //Get search dictionary
       NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
       //Delete old item before add new item
       SecItemDelete((CFDictionaryRef)keychainQuery);
       //Add new object to search dictionary(Attention:the data format)
       [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
       //Add item to keychain with the search dictionary
       SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
   }
   
   + (id)load:(NSString *)service {
       id ret = nil;
       NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
       //Configure the search setting
       //Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue
       [keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
       [keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
       CFDataRef keyData = NULL;
       if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
           @try {
               ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
           } @catch (NSException *e) {
               NSLog(@"Unarchive of %@ failed: %@", service, e);
           } @finally {
           }
       }
       if (keyData)
           CFRelease(keyData);
       return ret;
   }
   
   + (void)deleteKeyData:(NSString *)service {
       NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
       SecItemDelete((CFDictionaryRef)keychainQuery);
   }
   
    
@end

將這兩個類添加到工程中,使用方式如下

NSString * uuid= [UUID getUUID]

將程序?qū)懺谥笾匦掳惭b柬讨,我們依然能獲取同樣的UUID崩瓤。需要注意的是當(dāng)手機恢復(fù)出廠設(shè)置后獲取的UUID是不一樣的了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末踩官,一起剝皮案震驚了整個濱河市却桶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌卖鲤,老刑警劉巖肾扰,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件畴嘶,死亡現(xiàn)場離奇詭異蛋逾,居然都是意外死亡,警方通過查閱死者的電腦和手機窗悯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門区匣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事亏钩×拢” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵姑丑,是天一觀的道長蛤签。 經(jīng)常有香客問我,道長栅哀,這世上最難降的妖魔是什么震肮? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮留拾,結(jié)果婚禮上戳晌,老公的妹妹穿的比我還像新娘。我一直安慰自己痴柔,他們只是感情好沦偎,可當(dāng)我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著咳蔚,像睡著了一般豪嚎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谈火,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天疙渣,我揣著相機與錄音,去河邊找鬼堆巧。 笑死妄荔,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的谍肤。 我是一名探鬼主播啦租,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼荒揣!你這毒婦竟也來了篷角?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤系任,失蹤者是張志新(化名)和其女友劉穎恳蹲,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體俩滥,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡嘉蕾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了霜旧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片错忱。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出以清,到底是詐尸還是另有隱情儿普,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布掷倔,位于F島的核電站眉孩,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏勒葱。R本人自食惡果不足惜勺像,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望错森。 院中可真熱鬧吟宦,春花似錦、人聲如沸涩维。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓦阐。三九已至蜗侈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間睡蟋,已是汗流浹背踏幻。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留戳杀,地道東北人该面。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像信卡,于是被迫代替她去往敵國和親隔缀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容