iOS 設(shè)備的唯一標(biāo)識(shí)符

1.已禁用-[UIDevice uniqueIdentifier]
  蘋(píng)果總是把用戶(hù)的隱私看的很重要。-[UIDevice uniqueIdentifier]在iOS5實(shí)際在iOS5的時(shí)候已經(jīng)被遺棄了,但是iOS7中已經(jīng)完全的禁用了它。Xcode5甚至不會(huì)允許你編譯包含了指引到-[UIDevice uniqueIdentifier]的app。此外,iOS7之前的使用了-[UIDevice uniqueIdentifier] 的app如果在iOS7上運(yùn)行,它不會(huì)返回設(shè)備的UUID,而是會(huì)返回一串字符串,以FFFFFFFF開(kāi)頭,跟著-[UIDevice identifierForVendor]的十六進(jìn)制值。

2.MAC地址不能再用來(lái)設(shè)別設(shè)備
  還有一個(gè)生成iOS設(shè)備唯一標(biāo)示符的方法是使用iOS設(shè)備的Media Access Control(MAC)地址。一個(gè)MAC地址是一個(gè)唯一的號(hào)碼,它是物理網(wǎng)絡(luò)層級(jí)方面分配給網(wǎng)絡(luò)適配器的。這個(gè)地址蘋(píng)果還有其他的名字,比如說(shuō)是硬件地址(Hardware Address)或是Wifi地址,都是指同樣的東西。
  有很多工程和框架都使用這個(gè)方法來(lái)生成唯一的設(shè)備ID。比如說(shuō)ODIN。然而,蘋(píng)果并不希望有人通過(guò)MAC地址來(lái)分辨用戶(hù),所以如果你在iOS7系統(tǒng)上查詢(xún)MAC地址,它現(xiàn)在只會(huì)返回02:00:00:00:00:00。

3.現(xiàn)在蘋(píng)果明確的表明你應(yīng)該使用-[UIDevice identifierForVendor]或是-[ASIdentifierManager advertisingIdentifier]來(lái)作為你框架和應(yīng)用的唯一標(biāo)示符。坦白的來(lái)說(shuō),應(yīng)對(duì)這些變化也不是那么的難,見(jiàn)以下代碼片段:

NSString *identifierForVendor = [[UIDevice currentDevice].identifierForVendor UUIDString]; 
NSString *identifierForAdvertising = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString]; 

每種方法都適配一種特別的用法:
  identifierForVendor對(duì)供應(yīng)商來(lái)說(shuō)是唯一的一個(gè)值,也就是說(shuō),由同一個(gè)公司發(fā)行的的app在相同的設(shè)備上運(yùn)行的時(shí)候都會(huì)有這個(gè)相同的標(biāo)識(shí)符。然而,如果用戶(hù)刪除了這個(gè)供應(yīng)商的app然后再重新安裝的話(huà),這個(gè)標(biāo)識(shí)符就會(huì)不一致。
  advertisingIdentifier會(huì)返回給在這個(gè)設(shè)備上所有軟件供應(yīng)商相同的 一個(gè)值,所以只能在廣告的時(shí)候使用。這個(gè)值會(huì)因?yàn)楹芏嗲闆r而有所變化,比如說(shuō)用戶(hù)初始化設(shè)備的時(shí)候便會(huì)改變。

  1. 由于identifierForVendor刪除了這個(gè)供應(yīng)商的app然后再重新安裝的話(huà),這個(gè)標(biāo)識(shí)符就會(huì)不一致,所以要解決這個(gè)問(wèn)題可以把第一次生成的唯一標(biāo)示符,保存到keyChain(鑰匙串)中,當(dāng)應(yīng)用被刪除后keyChain中的數(shù)據(jù)還在,下次在從keyChain中取就OK了
    廢話(huà)就講到這了,下面是代碼:
#define KEY_UDID            @"KEY_UDID"  
#define KEY_IN_KEYCHAIN     @"KEY_IN_KEYCHAIN"  
  
#import <Security/Security.h>  
#import "APPIdentificationManage.h"  
  
@implementation APPIdentificationManage  
singleton_implementation(APPIdentificationManage)  
  
#pragma mark 獲取UUID  
/** 
 *此uuid在相同的一個(gè)程序里面-相同的vindor-相同的設(shè)備下是不會(huì)改變的 
 *此uuid是唯一的,但應(yīng)用刪除再重新安裝后會(huì)變化,采取的措施是:只獲取一次保存在鑰匙串中,之后就從鑰匙串中獲取 
 **/  
- (NSString *)openUDID  
{  
    NSString *identifierForVendor = [[UIDevice currentDevice].identifierForVendor UUIDString];  
    return identifierForVendor;  
}  
  
#pragma mark 保存UUID到鑰匙串  
- (void)saveUDID:(NSString *)udid  
{  
    NSMutableDictionary *udidKVPairs = [NSMutableDictionary dictionary];  
    [udidKVPairs setObject:udid forKey:KEY_UDID];  
    [[APPIdentificationManage sharedAPPIdentificationManage] save:KEY_IN_KEYCHAIN data:udidKVPairs];  
}  
  
#pragma mark 讀取UUID  
/** 
 *先從內(nèi)存中獲取uuid,如果沒(méi)有再?gòu)蔫€匙串中獲取,如果還沒(méi)有就生成一個(gè)新的uuid,并保存到鑰匙串中供以后使用 
 **/  
- (id)readUDID  
{  
    if (_uuid == nil || _uuid.length == 0) {  
        NSMutableDictionary *udidKVPairs = (NSMutableDictionary *)[[APPIdentificationManage sharedAPPIdentificationManage] load:KEY_IN_KEYCHAIN];  
        NSString *uuid = [udidKVPairs objectForKey:KEY_UDID];  
        if (uuid == nil || uuid.length == 0) {  
            uuid = [self openUDID];  
            [self saveUDID:uuid];  
        }  
        _uuid = uuid;  
    }  
    return _uuid;  
}  
  
#pragma mark 刪除UUID  
- (void)deleteUUID  
{  
    [APPIdentificationManage delete:KEY_IN_KEYCHAIN];  
}  
  
#pragma mark 查詢(xún)鑰匙串  
- (NSMutableDictionary *)getKeychainQuery:(NSString *)service {  
    return [NSMutableDictionary dictionaryWithObjectsAndKeys:  
            (__bridge_transfer id)kSecClassGenericPassword,(__bridge_transfer id)kSecClass,  
            service, (__bridge_transfer id)kSecAttrService,  
            service, (__bridge_transfer id)kSecAttrAccount,  
            (__bridge_transfer id)kSecAttrAccessibleAfterFirstUnlock,(__bridge_transfer id)kSecAttrAccessible,  
            nil nil];  
}  
  
#pragma mark 將數(shù)據(jù)保存到鑰匙串  
- (void)save:(NSString *)service data:(id)data {  
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];  
    SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery);  
    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge_transfer id)kSecValueData];  
    SecItemAdd((__bridge_retained CFDictionaryRef)keychainQuery, NULL);  
}  
  
#pragma mark 加載鑰匙串中數(shù)據(jù)  
- (id)load:(NSString *)service {  
    id ret = nil;  
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];  
  
    [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge_transfer id)kSecReturnData];  
    [keychainQuery setObject:(__bridge_transfer id)kSecMatchLimitOne forKey:(__bridge_transfer id)kSecMatchLimit];  
    CFDataRef keyData = NULL;  
    if (SecItemCopyMatching((__bridge_retained CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {  
        @try {  
            ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge_transfer NSData *)keyData];  
        } @catch (NSException *e) {  
            NSLog(@"Unarchive of %@ failed: %@", service, e);  
        } @finally {  
        }  
    }  
    return ret;  
}  
  
#pragma mark 刪除鑰匙串中數(shù)據(jù)  
- (void)delete:(NSString *)service {  
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];  
    SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery);  
}  
@end  
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容