iOS 设备唯一标识符


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


方案一

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

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

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

AdSupport.framework  

2、添加头文件

#import   

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  
@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  

@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 设备唯一标识符)