1. 程式人生 > >繼udid,Mac地址等一系列唯一標識無效後,如何用KeyChain來實現裝置唯一性

繼udid,Mac地址等一系列唯一標識無效後,如何用KeyChain來實現裝置唯一性

蘋果本著為使用者安全考慮的初衷導致UDID和Mac地址相繼陣亡,IMEI也不例外,為了裝置的唯一性,一代代開發者絞盡腦汁,後來KeyChain被他們瞄上了,終於可以繼續判別社別的唯一性。

原理是利用UUID,有人說,UUID是非唯一的,很容易變化,對,沒錯,但是UUID絕對不會重複對吧?所以UUID我只需要獲取一次,然後存入KeyChain,即使App被刪除了,KeyChain中的UUID也不會被刪除,如果你們公司有兩款App,完全可以通過存入的key值讀取出另一個App的UUID,做一些簡單的互動。

具體的實現方法,網上有很多種方法,很少有全套的使用方法,博主這裡重新總結了下:
先說說獲取UUID的方法:

 CFUUIDRef myUUID = CFUUIDCreate( nil );
    CFStringRef uuidString = CFUUIDCreateString( nil, myUUID );
    NSString * result = (NSString *)CFBridgingRelease(CFStringCreateCopy( NULL, uuidString));

關於實際的儲存,都是屬於套路的程式碼了,沒什麼可讀性,直接貼出來了:
有兩個管理類:

#import <Foundation/Foundation.h>

@interface LHUUIDManager
: NSObject
+(void)saveUUID; //儲存UUID +(id)readUUID; //獲取UUID +(void)deleteUUID; //刪除 @end #import "LHUUIDManager.h" #import "LHKeyChain.h" @implementation LHUUIDManager : NSObject static NSString * const KEY_IN_KEYCHAIN = @"KEY_IN_KEYCHAIN"; static NSString * const KEY_IN_UUID = @"KEY_IN_UUID"; +(void
)saveUUID { NSMutableDictionary *myUUIDDic = [NSMutableDictionary dictionary]; [myUUIDDic setObject:[self creatUUID] forKey:KEY_IN_UUID]; [LHKeyChain save:KEY_IN_KEYCHAIN data:myUUIDDic]; } +(id)readUUID { NSMutableDictionary *myUUIDDic = (NSMutableDictionary *)[LHKeyChain read:KEY_IN_KEYCHAIN]; return [myUUIDDic objectForKey:KEY_IN_UUID]; } +(void)deleteUUID { [LHKeyChain lhDelete:KEY_IN_KEYCHAIN]; } +(NSString *)creatUUID { CFUUIDRef myUUID = CFUUIDCreate( nil ); CFStringRef uuidString = CFUUIDCreateString( nil, myUUID ); NSString * result = (NSString *)CFBridgingRelease(CFStringCreateCopy( NULL, uuidString)); return result; } @end
#import <Foundation/Foundation.h>

@interface LHKeyChain : NSObject
+ (NSMutableDictionary *)getKeychain:(NSString *)keyChain ;

+ (void)save:(NSString *)keyChain data:(id)data;

+ (id)read:(NSString *)keyChain;

+ (void)lhDelete:(NSString *)keyChain;
@end





#import "LHKeyChain.h"

@implementation LHKeyChain
+ (NSMutableDictionary *)getKeychain:(NSString *)keyChain {
    return [NSMutableDictionary dictionaryWithObjectsAndKeys:
            (__bridge_transfer id)kSecClassGenericPassword,(__bridge_transfer id)kSecClass,
            keyChain, (__bridge_transfer id)kSecAttrService,
            keyChain, (__bridge_transfer id)kSecAttrAccount,
            (__bridge_transfer id)kSecAttrAccessibleAfterFirstUnlock,(__bridge_transfer id)kSecAttrAccessible,
            nil];
}

+ (void)save:(NSString *)keyChain data:(id)data {
    //Get search dictionary
    NSMutableDictionary *keychainQuery = [self getKeychain:keyChain];
    //Delete old item before add new item
    CFDictionaryRef aRef = (__bridge_retained CFDictionaryRef)keychainQuery;
    SecItemDelete(aRef);
    //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(aRef, NULL);
}

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

+ (void)lhDelete:(NSString *)keyChain {
    NSMutableDictionary *keychainQuery = [self getKeychain:keyChain];
    SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery);
}
@end

到這裡是所有關鍵程式碼,放上下載地址:點選下載

最後,忘了件重要的事情,要在xcode中啟用KeyChain:
這裡寫圖片描述
當顯示為ON的時候才能使用KeyChain。