zoukankan      html  css  js  c++  java
  • iOS编程——经过UUID和KeyChain来代替Mac地址实现iOS设备的唯一标示(OC版)

    iOS编程——通过UUID和KeyChain来代替Mac地址实现iOS设备的唯一标示(OC版)

    很多的应用都需要用到手机的唯一标示,而且要求这个唯一标示不能因为应用app的卸载或者改变而变化。

    在iOS7以前是可以通过Mac地址来实现这个功能的,但是iOS7(包含)以后是无法获得Mac地址的;苹果官方推荐使用UUID,但是每次随着APP的卸载重装,UUID会随之发生变化,那该如何处理呢?

    我们需要一个能在app卸载重装后不会改变的值,而keyChain恰巧就可以做到。配合UUID就可以实现了!让我们来分析下:

    1.我们首先需要导入Security.frameWork(keychain依赖它),然后需要一个keychain管理器,一个uuid管理器,文件组成如下:

    iOS编程——经过UUID和KeyChain来代替Mac地址实现iOS设备的唯一标示(OC版) - 操作系统

    2.首先来看MyKeychainManager,其实就是对keychain的增、删、改、查,类似于数据库的处理。

    先通过.h文件来开放下增、删、改、查四个接口:

    #import <Foundation/Foundation.h>
    
    @interface MyKeyChainManager : NSObject
    
    + (NSMutableDictionary *)getKeychainQuery:(NSString *)service;
    
    + (void)save:(NSString *)service data:(id)data;
    
    + (id)load:(NSString *)service;
    
    + (void)delete:(NSString *)service;
        
    @end
    
    
    
    

    .m文件实现接口,keychain的使用网上很多,直接贴代码了:

    #import "MyKeyChainManager.h"
    
    @implementation MyKeyChainManager : NSObject 
    
    + (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
        return [NSMutableDictionary dictionaryWithObjectsAndKeys:
                (__bridge_transfer id)kSecClassGenericPassword,(__bridge_transfer id)kSecClass,
                service, (__bridge_transfer id)kSecAttrService,
                service, (__bridge_transfer id)kSecAttrAccount,
                (__bridge_transfer id)kSecAttrAccessibleAfterFirstUnlock,(__bridge_transfer 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((__bridge_retained CFDictionaryRef)keychainQuery);
        //Add new object to search dictionary(Attention:the data format)
        [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge_transfer id)kSecValueData];
        //Add item to keychain with the search dictionary
        SecItemAdd((__bridge_retained CFDictionaryRef)keychainQuery, NULL);
    }
    
    + (id)load:(NSString *)service {
        id ret = nil;
        NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
        //Configure the search setting
        [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: %@", service, e);
            } @finally {
            }
        }
        return ret;
    }
    
    + (void)delete:(NSString *)service {
        NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
        SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery);
    }
    
    @end


    3.再来看下MyUUIDManager文件,实现的是对UUID的增、删、改、查,其中save既是增也是改:

    #import <Foundation/Foundation.h>
    
    @interface MyUUIDManager: NSObject
    
    +(void)saveUUID:(NSString *)uuid;
    
    +(NSString *)getUUID;
    
    +(void)deleteUUID;
    
    @end


    .m文件来实现它:

    #import "MyUUIDManager.h"
    #import "MyKeyChainManager.h"
    
    @implementation MyUUIDManager
    
    static NSString * const KEY_IN_KEYCHAIN = @"com.myuuid.uuid";
    
    
    +(void)saveUUID:(NSString *)uuid{
        if (uuid && uuid.length > 0) {
            [MyKeyChainManager save:KEY_IN_KEYCHAIN data:uuid];
        }
    }
    
    
    +(NSString *)getUUID{
        //先获取keychain里面的UUID字段,看是否存在
        NSString *uuid = (NSString *)[MyKeyChainManager load:KEY_IN_KEYCHAIN];
        
        //如果不存在则为首次获取UUID,所以获取保存。
        if (!uuid || uuid.length == 0) {
            CFUUIDRef puuid = CFUUIDCreate( nil );
            
            CFStringRef uuidString = CFUUIDCreateString( nil, puuid );
            
            uuid = [NSString stringWithFormat:@"%@", uuidString];
            
            [self saveUUID:uuid];
            
            CFRelease(puuid);
            
            CFRelease(uuidString);
        }
        
        return uuid;
    }
    
    
    
    +(void)deleteUUID{
        [MyKeyChainManager delete:KEY_IN_KEYCHAIN];
    }
    
    
    @end


    4.测试一下:

    NSString *uuid = [MyUUIDManager getUUID];
        NSLog(@"uuid: %@",uuid);
    2015-08-10 18:14:07.641 MyTest[3190:220331] uuid: 839E055B-09A5-42E1-A46C-DF4481E23333


    5.把app删除掉重新安装一下,再打印一下:

    2015-08-10 18:22:37.122 MyTest[3214:222053] uuid: 839E055B-09A5-42E1-A46C-DF4481E23333
    
    
  • 相关阅读:
    ReactNative: 数据请求
    ReactNative: 使用Geolocation的API获取位置信息
    ReactNative: 使用第三方库图像选择器react-native-image-picker和react-native-image-crop-picker
    MDG_TR_DEST
    【VerySky原创】后台JOB运行-相关表
    【VerySky原创】RPR_ABAP_SOURCE_SCAN
    【VerySky原创】 ME9F
    【VerySky原创】如何查找SNRO编号范围的使用情况;
    【VerySky原创】怎样查找到CDHDR、CDPOS表中的OBJECTCLAS字段
    【由VerySky原创】由Number Range 导致凭证生成但无法保存的问题
  • 原文地址:https://www.cnblogs.com/DoNetCShap/p/5175401.html
Copyright © 2011-2022 走看看