iOS 唯一識別碼 IDFV+keychain


   

     這段時間用到了iPhone的唯一標識,找到了不少方法,認為較好用的且現在可行的有兩種。一是IDFV另一個是IDFA,前者identifierForVendor是apple給供應商唯一的一個值,也就是說同一個公司發行的的app在相同的設備上運行的時候會有這個相同的標識符。然而,如果用戶刪除了這個供應商的所有app然后再重新安裝的話,這個標識符就會不一致。后者advertisingIdentifier則是給在這個設備上所有軟件供應商相同的一個值,一般在廣告的時候使用。這個值雖然不會因為重裝app改變,但是在某些情況下還是會改變。如果用戶完全重置系統((設置程序 -> 通用 -> 還原 -> 還原位置與隱私) ,這個廣告標示符會重新生成。另外如果用戶明確的還原廣告(設置程序-> 通用 -> 關於本機 -> 廣告 -> 還原廣告標示符) ,那么廣告標示符也會重新生成。關於廣告標示符的還原,還有一點需要注意:如果程序在后台運行,此時用戶“還原廣告標示符”,然后再回到程序中,此時獲取廣告標示符並不會立即獲得還原后的標示符。必須要終止程序,然后再重新啟動程序,才能獲得還原后的廣告標示符。

獲取方法如下:

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

相比卸載重裝,IDFA還是較穩定的,但是用IDFA在送審的時候,要表明用了廣告標識符,並且要導入依賴庫,為了不引起必要麻煩,本人采用了IDFV+keychain的方法。keychain是iPhone的一個機制。將信息保存在系統,這些信息不隨app的卸載重裝而消失。

先簡單介紹下IDFA的導入方法:

---------------------------------------------------------------------------

1、添加框架       本人剛開始導入的是security.framework  測試也可以使用

AdSupport.framework

2、添加頭文件
#import <AdSupport/ASIdentifierManager.h>

3、使用語句
NSString *IDFA = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];

-----------------------------------------------------------------------------

 

重點是IDFV+keychain這種方法 封裝在一個工具類中 非常好用   ok上代碼

Tools.h中

+++++++++++++++++++++

+ (void)save:(NSString *)service data:(id)data;

+ (id)load:(NSString *)service;

+ (void)delete:(NSString *)service;

+ (NSString *)getIDFV;

++++++++++++++++++++++

Tools.m中

=================================

+ (NSString *)getIDFV

{

    //定義存入keychain中的賬號 也就是一個標識 表示是某個app存儲的內容   bundle id就好

    NSString * const KEY_USERNAME_PASSWORD = @"com.danson.zzzz.usernamepassword";

    NSString * const KEY_PASSWORD = @"com.danson.zzzz.password";

    

    //測試用 清除keychain中的內容

    //[Tools delete:KEY_USERNAME_PASSWORD];

    //讀取賬號中保存的內容

    NSMutableDictionary *readUserPwd = (NSMutableDictionary *)[Tools load:KEY_USERNAME_PASSWORD];

    //NSLog(@"keychain------><>%@",readUserPwd);

  

    if (!readUserPwd) {

        //如果為空 說明是第一次安裝 做存儲操作

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

        //NSLog(@"identifierStr-----><>%@",identifierStr);

        NSMutableDictionary *usernamepasswordKVPairs = [NSMutableDictionary dictionaryWithObject:identifierStr forKey:KEY_PASSWORD];

        [Tools save:KEY_USERNAME_PASSWORD data:usernamepasswordKVPairs];

        return identifierStr;

    }else{

        return [readUserPwd objectForKey:KEY_PASSWORD];

    }

}

 

//儲存

+ (void)save:(NSString *)service data:(id)data {

    //Get search dictionary

    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];

    //Delete old item before add new item

    SecItemDelete((__bridge CFDictionaryRef)keychainQuery);

    //Add new object to search dictionary(Attention:the data format)

    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge id)kSecValueData];

    //Add item to keychain with the search dictionary

    SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);

}

 

+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service {

    return [NSMutableDictionary dictionaryWithObjectsAndKeys:

            (__bridge id)kSecClassGenericPassword,(__bridge id)kSecClass,

            service, (__bridge id)kSecAttrService,

            service, (__bridge id)kSecAttrAccount,

            (__bridge id)kSecAttrAccessibleAfterFirstUnlock,(__bridge id)kSecAttrAccessible,

            nil];

}

 

//取出

+ (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:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];

    [keychainQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];

    CFDataRef keyData = NULL;

    if (SecItemCopyMatching((__bridge 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)delete:(NSString *)service {

    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];

    SecItemDelete((__bridge CFDictionaryRef)keychainQuery);

}

 ================================

 

調用的時候

直接 [Tools getIDFV] 就可以了   暫時還不知道 系統會不會把卸載重裝前生成的IDFA給別的開發商 如果會重新分配 就可能會產生重復的 待考證

 

ok 到這里就結束了  希望可以讓閱讀者節省點時間

 

 

參考資料  http://www.cnblogs.com/qingjoin/p/3549325.html  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM