美文网首页
iOS 设备唯一标识符

iOS 设备唯一标识符

作者: flyhao | 来源:发表于2016-05-11 11:44 被阅读151次

    心境自然凉,凉,凉,37度都要化了。早起顶着太阳走到公司,既能锻炼身体又能思考问题,我不会说太阳烤死了,走一路要40分钟,晒的透透的,吃了个面包,喝了盒酸奶,很营养,这酸奶一定有问题,闹肚子。又能愉快的写代码了,设计没有,后台没更新,我了个擦擦


    方案一

    回归正题了,咳咳
    iOS6 之前用的Mac地址,但在iOS7以后会返回固定值,方法失效,才有了今天的讨论。

    IDFA这是iOS 6中另外一个新的方法,是AdSupport.framework框架中ASIdentifierManager单例提供了一个方法advertisingIdentifier,通过调用该方法会返回一个的NSUUID实例。这一段是我无耻抄的

    作为唯一标识符,两个思路。第一,程序生成,但保证每次生成结果一致并唯一。第二,程序每次生成不一致,但由系统存储,不由程序沙盒管理。
    IDFA是由系统存储的,并且每次生成都是一致,太好了,可以拿来用。但万物都不可能是完美的,用它需要注意,在往App Store提交时,对于广告选择选择234。再有IDFA 有心的被重置的风险较大,所以这里并不十分推荐,无论如何还是要写上步骤。
    1、添加框架

    AdSupport.framework  
    

    2、添加头文件

    #import <AdSupport/ASIdentifierManager.h>  
    

    3、使用语句

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

    方案二

    UUID+keychain

    接下来我摘抄的keychain为钥匙串,用来存储密码和证书的一块加密存储区域,keychain不是存储在手机的沙盒内,而是手机的某个公共区域,手机重启和应用卸载,都不会对这片存储区域造成影响,因为是加密存储不存在被其他应用修改的问题,所以就有人拿keychain来存储唯一标识。
    UUID是随机的唯一 数字串,作为设备唯一标识。
    两者结合实现了设备唯一标识,当然这个想法是别人想出来的。
    直接上步骤快到饭点了
    1.Target - Capabilities - Keychain Sharing - ON,左侧的目录会自动生成Entitlements文件,Bundle Identifier、Keychain Sharing的Keychain Groups、Entitlements文件的Keychain Access Groups的第一个元素,它们要保持一致性。
    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"];
        
        //首次执行该方法时,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
    
    

    在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 你要的在这
    

    相比心静自然凉,倒觉得心凉自然静,更有道理。

    相关文章

      网友评论

          本文标题:iOS 设备唯一标识符

          本文链接:https://www.haomeiwen.com/subject/dqxurttx.html