iOS-设置uuid卸载安装后保持不变问题
参考: iOS获取UUID(唯一不变哦)
UUIDString 的理解
因为系统的获取方法[UIDevice currentDevice].identifierForVendor.UUIDString
拿到的uuidstring
,再次卸载后,有可能会变化,所以不能保证拿到的值是唯一不变的。
需要将获取到的值保存到钥匙串来保证卸载重装之后,能取到不变的值。
先配置项目打开钥匙串权限:
实现保存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