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


心境自然涼,涼,涼,37度都要化了。早起頂著太陽走到公司,既能鍛煉身體又能思考問題,我不會(huì)說太陽烤死了,走一路要40分鐘,曬的透透的,吃了個(gè)面包,喝了盒酸奶,很營(yíng)養(yǎng),這酸奶一定有問題,鬧肚子。又能愉快的寫代碼了,設(shè)計(jì)沒有,后臺(tái)沒更新,我了個(gè)擦擦。


方案一

回歸正題了,咳咳
iOS6 之前用的Mac地址,但在iOS7以后會(huì)返回固定值,方法失效,才有了今天的討論。

IDFA這是iOS 6中另外一個(gè)新的方法,是AdSupport.framework框架中ASIdentifierManager單例提供了一個(gè)方法advertisingIdentifier,通過調(diào)用該方法會(huì)返回一個(gè)的NSUUID實(shí)例。這一段是我無恥抄的

作為唯一標(biāo)識(shí)符,兩個(gè)思路。第一,程序生成,但保證每次生成結(jié)果一致并唯一。第二,程序每次生成不一致,但由系統(tǒng)存儲(chǔ),不由程序沙盒管理。
IDFA是由系統(tǒng)存儲(chǔ)的,并且每次生成都是一致,太好了,可以拿來用。但萬物都不可能是完美的,用它需要注意,在往App Store提交時(shí),對(duì)于廣告選擇選擇234。再有IDFA 有心的被重置的風(fēng)險(xiǎn)較大,所以這里并不十分推薦,無論如何還是要寫上步驟。
1、添加框架

AdSupport.framework  

2、添加頭文件

#import <AdSupport/ASIdentifierManager.h>  

3、使用語句

NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];  

方案二

UUID+keychain

接下來我摘抄的keychain為鑰匙串,用來存儲(chǔ)密碼和證書的一塊加密存儲(chǔ)區(qū)域,keychain不是存儲(chǔ)在手機(jī)的沙盒內(nèi),而是手機(jī)的某個(gè)公共區(qū)域,手機(jī)重啟和應(yīng)用卸載,都不會(huì)對(duì)這片存儲(chǔ)區(qū)域造成影響,因?yàn)槭羌用艽鎯?chǔ)不存在被其他應(yīng)用修改的問題,所以就有人拿keychain來存儲(chǔ)唯一標(biāo)識(shí)。
UUID是隨機(jī)的唯一 數(shù)字串,作為設(shè)備唯一標(biāo)識(shí)。
兩者結(jié)合實(shí)現(xiàn)了設(shè)備唯一標(biāo)識(shí),當(dāng)然這個(gè)想法是別人想出來的。
直接上步驟快到飯點(diǎn)了
1.Target - Capabilities - Keychain Sharing - ON,左側(cè)的目錄會(huì)自動(dòng)生成Entitlements文件,Bundle Identifier、Keychain Sharing的Keychain Groups、Entitlements文件的Keychain Access Groups的第一個(gè)元素,它們要保持一致性。
2.上代碼 這里是借鑒鐘溪妍的,她copy的百度的,百度拿的誰的
UUID.h

#import  <Foundation/Foundation.h>
@interface UUID : NSObject
+(NSString *)getUUID;

UUID.m

#import "UUID.h"
#import "KeyChainStore.h"


@implementation UUID

+(NSString *)getUUID
{
    NSString * strUUID = (NSString *)[KeyChainStore load:@"com.company.app.usernamepassword"];
    
    //首次執(zhí)行該方法時(shí),uuid為空
    if ([strUUID isEqualToString:@""] || !strUUID)
    {
        //生成一個(gè)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

在PCH中添加如下宏

#ifndef PrefixHeader_pch
#define PrefixHeader_pch

#define  KEY_USERNAME_PASSWORD @"com.company.app.usernamepassword"
#define  KEY_USERNAME @"com.company.app.username"
#define  KEY_PASSWORD @"com.company.app.password"

#endif

最后的最后

 NSString * uuid= [UUID getUUID];
  NSLog(@"uuid=%@",uuid);
//  uuid 你要的在這

相比心靜自然涼,倒覺得心涼自然靜,更有道理。

最后編輯于
?著作權(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)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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