iOS获取手机唯一标示

随着苹果爸爸的不断改革,现在想获取一台手机的唯一标示是难上加难,但是办法还是有的,下面就来介绍一下最简单安全的办法,获取手机唯一标示。(首先说明这种方法的弊端,手机系统升级后这个唯一的ID也会变化)

以前废弃的方法就不一一细说了,直接说笔者是怎么做的吧

  • 采用Keychain+[[NSUUID UUID] UUIDString] 的方法

开发者可以在应用第一次启动时仅仅调用一次,然后利用Keychain将该串存储起来,如果Keychain存储了UUID就不需要再存储了。如果用户删除该应用再次安装时,Keychain存储的UUID也不会消失,所以能保证唯一识别该设备。

  • keychain介绍
    iOS的keychain服务提供了一种安全的保存私密信息(密码,序列号,证书等)的方式,每个ios程序都有一个独立的keychain存储。相对于NSUserDefaults、文件保存等一般方式,keychain保存更为安全,而且keychain里保存的信息不会因App被删除而丢失,所以在重装App后,keychain里的数据还能使用。

  • keychain代码

#import 
#import 

NS_ASSUME_NONNULL_BEGIN

@interface ZXXKeyChain : NSObject


/**
 添加keyChain数据

 @param data s数据
 @param key key值
 */
+ (void)addKeychainData:(id)data forKey:(NSString *)key;

/**
 根据key值获取数据

 @param key key值
 @return 返回数据
 */
+ (id)getKeychainDataForKey:(NSString *)key;

/**
 根据key值删除数据

 @param key key值
 */
+ (void)deleteKeychainDataForKey:(NSString *)key;

@end

NS_ASSUME_NONNULL_END
#import "ZXXKeyChain.h"


@implementation ZXXKeyChain


+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
    return [NSMutableDictionary dictionaryWithObjectsAndKeys:
            (__bridge id)kSecClassGenericPassword,(id)kSecClass,// 标识符(kSecAttrGeneric通常值位密码)
            service, (__bridge id)kSecAttrService,// 服务(kSecAttrService)
            service, (__bridge id)kSecAttrAccount,// 账户(kSecAttrAccount)
            (__bridge id)kSecAttrAccessibleAfterFirstUnlock,(__bridge id)kSecAttrAccessible,// kSecAttrAccessiblein变量用来指定这个应用何时需要访问这个数据
            nil];
}

+ (void)addKeychainData:(id)data forKey:(NSString *)key {
    // 获取查询字典
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:key];
    // 在添加之前先删除旧数据
    SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
    // 添加新的数据到字典
    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge id)kSecValueData];
    // 将数据字典添加到钥匙串
    SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);
}

+ (id)getKeychainDataForKey:(NSString *)key {
    id ret = nil;
    NSMutableDictionary *keychainQuery = [self getKeychainQuery: key];
    
    [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: %@", key, e);
        } @finally {
            
        }
    }
    
    return ret;
}

+ (void)deleteKeychainDataForKey:(NSString *)key {
    NSMutableDictionary *keychainQuery = [self getKeychainQuery: key];
    SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery);
}
  • 具体实现在AppDelegate实现以下代码
- (void)creatOnlyID{
    NSString *uuidStr = [[NSUUID UUID] UUIDString];
    NSString *getStr = [ZXXKeyChain getKeychainDataForKey:@"UUID"];
    if (getStr.length == 0) {
        [ZXXKeyChain addKeychainData:uuidStr forKey:@"UUID"];
    }
}

这种方法还是存在问题,当手机系统升级后,KeyChain中存储的值会变化,现在还没有好的对策,欢迎大神@指正

你可能感兴趣的:(iOS获取手机唯一标示)