iOS-uuid保持唯一的方法

iOS-设置uuid卸载安装后保持不变问题

参考: iOS获取UUID(唯一不变哦)

UUIDString 的理解

因为系统的获取方法[UIDevice currentDevice].identifierForVendor.UUIDString 拿到的uuidstring,再次卸载后,有可能会变化,所以不能保证拿到的值是唯一不变的。

需要将获取到的值保存到钥匙串来保证卸载重装之后,能取到不变的值。
先配置项目打开钥匙串权限:
iOS-uuid保持唯一的方法_第1张图片

实现保存keychain的方法后,获取uuid可以通过gleGetKeyCWithUUIDKey的方法来拿到唯一不变的值。

uuid说明

UUIDString 的理解
[UIDevice currentDevice].identifierForVendor.UUIDString
通过系统提供的获取uuidstring 的方式返回的由数字和字母组成的用来标识唯一设备的字符串。
identifierForVendor
一个由字母和数字组成的字符串,唯一地将设备标识给应用程序的供应商
按个人理解,就是uuidstring的变化,有vendor决定。 如果同一厂商有不同的app,同时存在,删除某一个(A),则在重新安装那一个(A),A的uuidstring还是不变的,不会重置,如果该厂商下的app全部删除了,那么A的uuidstring就会被重置。

代码参考

[UIDevice currentDevice].identifierForVendor.UUIDString
通过系统提供的获取uuidstring 的方式返回的由数字和字母组成的用来标识唯一设备的字符串。

保存到keychain到方法如下:

//  GLEKeyCStore.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN

@interface GLEKeyCStore : NSObject
+ (void)gleSave:(NSString*)service data:(id)data;
+ (id)gleLoad:(NSString*)service;
+ (void)gleDeleteKeyData:(NSString*)service;
+ (NSString *)gleGetKeyCWithUUIDKey:(NSString *)uuidKey;
@end

NS_ASSUME_NONNULL_END

//  GLEKeyCStore.m
#import "GLEKeyCStore.h"
@implementation GLEKeyCStore

+ (NSMutableDictionary *)gleGetKeyChainQuery:(NSString *)service {
    return [NSMutableDictionary dictionaryWithObjectsAndKeys:
            (id)kSecClassGenericPassword, (id)kSecClass,
            service, (id)kSecAttrService,
            service, (id)kSecAttrAccount,
            (id)kSecAttrAccessibleAfterFirstUnlock, (id)kSecAttrAccessible,
            nil];
}

+ (void)gleSave:(NSString *)service data:(id)data {
    NSMutableDictionary *keyCQuery = [self gleGetKeyChainQuery:service];
    
    SecItemDelete((CFDictionaryRef)keyCQuery);
    [keyCQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
    SecItemAdd((CFDictionaryRef)keyCQuery, NULL);
}

+ (id)gleLoad:(NSString *)service {
    id ret = nil;
    NSMutableDictionary *keyCQery = [self gleGetKeyChainQuery:service];
    [keyCQery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
    [keyCQery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
    CFDataRef keyData = NULL;
    if (SecItemCopyMatching((CFDictionaryRef)keyCQery, (CFTypeRef *)&keyData) == noErr) {
        @try {
            ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge  NSData *)keyData];
        } @catch (NSException *exception) {
            DEBUGLog(@"saveKeyStore: unarchiveof %@", service, exception);
        } @finally {
            
        }
    }
    if (keyData) {
        CFRelease(keyData);
    }
    return ret;
}

+ (void)gleDeleteKeyData:(NSString *)service {
    NSMutableDictionary *keyCQuery = [self gleGetKeyChainQuery:service];
    SecItemDelete((CFDictionaryRef)keyCQuery);
}

 
+ (NSString *)gleGetKeyCWithUUIDKey:(NSString *)uuidKey {
    // uuid 通过系统方法第一次拿到uuid的值,然后保存到keychain,主要是通过ad的方式,用户拒绝的话有可能拿到空值,所以直接取了uuidstring的值,该值也可以通过算法自己生成,需要保持唯一。
    // key 直接用的bundId
    NSString *tmpKeyStr = [NSBundle mainBundle].bundleIdentifier;
    NSString *strUUID = (NSString *)[GLEKeyCStore gleLoad:tmpKeyStr];
    if ((!strUUID) || (strUUID.length == 0) || [strUUID isEqual:@""]) {
        strUUID = [tmpKeyStr stringByAppendingFormat:@"%@-suijichuan", [[UIDevice currentDevice].identifierForVendor UUIDString]];
        [GLEKeyCStore gleSave:tmpKeyStr data:strUUID];
    }
    return strUUID;
}
@end

你可能感兴趣的:(OC,个人笔记,ios,objective-c,xcode)