前言
昨天有個小伙伴問我怎么去做設備的唯一標示碼,就像之前的糯米一樣,不論卸載了還是怎么的,都會記住你這個手機。給他說用uuid去做,結果人家還是沒做成。給他的一個Demo,在這也放上,給有同樣疑惑的伙伴。
Demo
正文
其實我做的這一種原理很簡單,uuid大家知道是設備對應用的唯一標示,但是有一個問題是當應用卸載了之后,再次下載對應應用的uuid就會改變。這就絕壁不行呀。所以怎么辦呢?我們可以把這個uuid存儲在本地,然后在應用再次安裝打開的時候去判斷是否有這個uuid數據,不就知道之前有沒有安裝過這個應用了。思路知道了,就改擼碼了。選用的存儲方式是keyChain,如果你不知道為什么選用這個方式去存儲的話,度娘一下(這個東西很好用,你需要知道)。
核心代碼:
//根據service去獲取他對應的在文件里面的數據字典
+ (NSMutableDictionary *)keyChainQueryDictionaryWithService:(NSString *)service{
NSMutableDictionary *keyChainQueryDictaionary = [[NSMutableDictionary alloc]init];
[keyChainQueryDictaionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
[keyChainQueryDictaionary setObject:service forKey:(id)kSecAttrService];
[keyChainQueryDictaionary setObject:service forKey:(id)kSecAttrAccount];
return keyChainQueryDictaionary;
}
//往本地數據字典里面去添加自己的數據
+ (BOOL)addData:(id)data forService:(NSString *)service{
NSMutableDictionary *keychainQuery = [self keyChainQueryDictionaryWithService:service];
SecItemDelete((CFDictionaryRef)keychainQuery);
[keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
OSStatus status= SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
if (status == noErr) {
return YES;
}
return NO;
}
//獲取對應的數據
+ (id)queryDataWithService:(NSString *)service {
id result;
NSMutableDictionary *keyChainQuery = [self keyChainQueryDictionaryWithService:service];
[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 {
result = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
}
@catch (NSException *exception) {
NSLog(@"不存在數據");
}
@finally {
}
}
if (keyData) {
CFRelease(keyData);
}
return result;
}
//更新對應的service 的數據
+ (BOOL)updateData:(id)data forService:(NSString *)service{
NSMutableDictionary *searchDictionary = [self keyChainQueryDictionaryWithService:service];
if (!searchDictionary) {
return NO;
}
NSMutableDictionary *updateDictionary = [[NSMutableDictionary alloc] init];
[updateDictionary setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
OSStatus status = SecItemUpdate((CFDictionaryRef)searchDictionary,
(CFDictionaryRef)updateDictionary);
if (status == errSecSuccess) {
return YES;
}
return NO;
}
//刪除不用的本地數據
+ (BOOL)deleteDataWithService:(NSString *)service{
NSMutableDictionary *keyChainDictionary = [self keyChainQueryDictionaryWithService:service];
OSStatus status = SecItemDelete((CFDictionaryRef)keyChainDictionary);
if (status == noErr) {
return YES;
}
return NO;
}
然后來一個管理類去調用他:
//增加一個
+ (void)addDataToKeyChain:(NSString *)chainKey dataString:(id)dataString{
[SYFKeyChain addData:dataString forService:chainKey];
}
//搜索一個
+ (NSString *)queryDataToKeyChain:(NSString *)chainKey{
return (NSString *)[SYFKeyChain queryDataWithService:chainKey];
}
//更新一個
+ (void)updateDatatKeyChain:(NSString *)chainKey dataString:(id)dataString{
[SYFKeyChain updateData:dataString forService:chainKey];
}
//刪除一個
+ (void)deleteDataKeyChain:(NSString *)chainKey{
[SYFKeyChain deleteDataWithService:chainKey];
}
最后就是使用他了:
//首先去獲取本地數據uuid,看是否存在
NSString *uuid = [SYFManagerKeyChain queryDataToKeyChain:UUID_KEY];
if ([uuid isKindOfClass:[NSNull class]] || uuid == nil || [uuid isEqualToString:@""]) {
//說明本地沒有存儲uuid
self.tinLabel.text = @"這是第一次安裝本應用,??歡迎使用";
//獲取到系統的uuid
uuid = [[NSUUID UUID] UUIDString];
//把uuid保存到本地數據
[SYFManagerKeyChain addDataToKeyChain:UUID_KEY dataString:uuid];
}else{
//說明本地存儲著uuid
self.tinLabel.text = @"??歡迎您回來繼續使用,??????";
}
//顯示uuid
self.uuidLabel.text = uuid;
顯示效果:
效果
結語
很簡單的一個東西,個人感覺沒有必要太多介紹。可以去下載Demo看一下,一運行,基本暢通。