日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

(绝对有用)iOS获取UUID,并使用keychain存储

發布時間:2025/3/15 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (绝对有用)iOS获取UUID,并使用keychain存储 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原文鏈接 http://blog.sina.com.cn/s/blog_5971cdd00102vqgy.html

?

UDID被棄用,使用UUID來作為設備的唯一標識。獲取到UUID后,如果用NSUserDefaults存儲,當程序被卸載后重裝時,再獲得的UUID和之前就不同了。使用keychain存儲可以保證程序卸載重裝時,UUID不變。但當刷機或者升級系統后,UUID還是會改變的。但這仍是目前為止最佳的解決辦法了,如果有更好的解決辦法,歡迎留言。

(我整理的解決辦法的參考來源:http://blog.k-res.net/archives/1081.html) 給大家兩個類: UUID.h中的代碼:

#import 尖括號(Foundation/Foundation.h)


@interface UUID : NSObject


+(NSString *)getUUID;


@end


?

UUID.m中的代碼:

#import "UUID.h"

#import?尖括號(Foundation/Foundation.h)

#import "KeychainItemWrapper.h"



@implementation UUID


+(NSString *)getUUID

{

? ? KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc]

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?initWithIdentifier:@"UUID"

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?accessGroup:@"YOUR_BUNDLE_SEED.com.yourcompany.userinfo"];


? ?

? ?NSString *strUUID = [keychainItem objectForKey:(id)CFBridgingRelease(kSecValueData)];


? ? //首次執行該方法時,uuid為空

? ?if ([strUUID isEqualToString:@""])


? ? {

? ? ? ? CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);


? ? ? ? strUUID = (NSString *)CFBridgingRelease(CFUUIDCreateString (kCFAllocatorDefault,uuidRef));


? ? ? ? [keychainItem setObject:strUUID forKey:(id)CFBridgingRelease(kSecValueData)];

??

? ? }

? ?return strUUID;

}


@end


第二個類是蘋果官方的一個Demo里封裝的,Demo的下載地址:http://developer.apple.com/library/ios/#samplecode/GenericKeychain/Listings/Classes_KeychainItemWrapper_h.html#//apple_ref/doc/uid/DTS40007797-Classes_KeychainItemWrapper_h-DontLinkElementID_9


KeychainItemWrapper.h中的代碼:


#import 尖括號(UIKit/UIKit.h)


@interface KeychainItemWrapper : NSObject

{

? ? NSMutableDictionary *keychainItemData;

? ? NSMutableDictionary *genericPasswordQuery;

}


@property (nonatomic, retain) NSMutableDictionary *keychainItemData;

@property (nonatomic, retain) NSMutableDictionary *genericPasswordQuery;


- (id)initWithIdentifier: (NSString *)identifier accessGroup:(NSString *) accessGroup;

- (void)setObject:(id)inObject forKey:(id)key;

- (id)objectForKey:(id)key;

- (void)resetKeychainItem;


@end


KeychainItemWrapper.m中的代碼:


#import "KeychainItemWrapper.h"

#import 尖括號(Security/Security.h)


@interface KeychainItemWrapper (PrivateMethods)


- (NSMutableDictionary *)secItemFormatToDictionary:(NSDictionary *)dictionaryToConvert;

- (NSMutableDictionary *)dictionaryToSecItemFormat:(NSDictionary *)dictionaryToConvert;


- (void)writeToKeychain;


@end


@implementation KeychainItemWrapper


@synthesize keychainItemData, genericPasswordQuery;


- (id)initWithIdentifier: (NSString *)identifier accessGroup:(NSString *) accessGroup;

{

? ?if (self = [super init])

? ? {

? ? ? ? ?genericPasswordQuery = [[NSMutableDictionary alloc] init];

?? ? ? ?

[genericPasswordQuery setObject:(id)CFBridgingRelease(kSecClassGenericPassword) forKey:(id)kSecClass];

? ? ? ? [genericPasswordQuery setObject:identifier forKey:(id)CFBridgingRelease(kSecAttrGeneric)];

?

if (accessGroup != nil)

{

#if TARGET_IPHONE_SIMULATOR

?

#else

[genericPasswordQuery setObject:accessGroup forKey:(id)kSecAttrAccessGroup];

#endif

}

?

?

? ? ? ? [genericPasswordQuery setObject:(id)CFBridgingRelease(kSecMatchLimitOne) forKey:(id)kSecMatchLimit];

? ? ? ? [genericPasswordQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];

?? ? ? ?

? ? ? ?NSDictionary *tempQuery = [NSDictionary dictionaryWithDictionary:genericPasswordQuery];

?? ? ? ?

? ? ? ?NSMutableDictionary *outDictionary = nil;

?? ? ? ?

? ? ? ?if (! SecItemCopyMatching((CFDictionaryRef)tempQuery, (CFTypeRef *)&outDictionary) == noErr)

? ? ? ? {

? ? ? ? ? ??

? ? ? ? ? ? [self resetKeychainItem];

?

[keychainItemData setObject:identifier forKey:(id)kSecAttrGeneric];

if (accessGroup != nil)

{

#if TARGET_IPHONE_SIMULATOR

?

#else

[keychainItemData setObject:accessGroup forKey:(id)kSecAttrAccessGroup];

#endif

}

}

? ? ? ?else

? ? ? ? {

? ? ? ? ? ?self.keychainItemData = [self secItemFormatToDictionary:outDictionary];

? ? ? ? }

? ? ? ?

[outDictionary release];

? ? }

?? ?

return self;

}


- (void)dealloc

{

? ? [keychainItemData release];

? ? [genericPasswordQuery release];

?? ?

[super dealloc];

}


- (void)setObject:(id)inObject forKey:(id)key?

{

? ?if (inObject == nil) return;

? ?id currentObject = [keychainItemData objectForKey:key];

? ?if (![currentObject isEqual:inObject])

? ? {

? ? ? ? [keychainItemData setObject:inObject forKey:key];

? ? ? ? [self writeToKeychain];

? ? }

}


- (id)objectForKey:(id)key

{

? ? return [keychainItemData objectForKey:key];

}


- (void)resetKeychainItem

{

OSStatus junk = noErr;

? ? if (!keychainItemData)?

? ? {

? ? ? ?self.keychainItemData = [[NSMutableDictionary alloc] init];

? ? }

? ? else if (keychainItemData)

? ? {

? ? ? ?NSMutableDictionary *tempDictionary = [self dictionaryToSecItemFormat:keychainItemData];

junk = SecItemDelete((CFDictionaryRef)tempDictionary);

? ? ? ? NSAssert( junk == noErr || junk == errSecItemNotFound, @"Problem deleting current dictionary." );

? ? }

?? ?

? ? [keychainItemData setObject:@"" forKey:(id)kSecAttrAccount];

? ? [keychainItemData setObject:@"" forKey:(id)kSecAttrLabel];

? ? [keychainItemData setObject:@"" forKey:(id)kSecAttrDescription];?

? [keychainItemData setObject:@"" forKey:(id)kSecValueData];

}


- (NSMutableDictionary *)dictionaryToSecItemFormat:(NSDictionary *)dictionaryToConvert

{

? ?NSMutableDictionary *returnDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert];

? ? [returnDictionary setObject:(id)kSecClassGenericPasswordforKey:(id)kSecClass];

??NSString *passwordString = [dictionaryToConvert objectForKey:(id)kSecValueData];

? ? [returnDictionary setObject:[passwordString dataUsingEncoding:NSUTF8StringEncoding] forKey:(id)kSecValueData];

?? ?

? ?return returnDictionary;

}


- (NSMutableDictionary *)secItemFormatToDictionary:(NSDictionary *)dictionaryToConvert

{

? ?NSMutableDictionary *returnDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert];

? ??[returnDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];

? ? ? ? ?[returnDictionary setObject:(id)kSecClassGenericPasswordforKey:(id)kSecClass];

? ? ?NSData *passwordData = NULL;

? ?if (SecItemCopyMatching((CFDictionaryRef)returnDictionary, (CFTypeRef *)&passwordData) == noErr)

? ? {

? ? ? ??[returnDictionary removeObjectForKey:(id)kSecReturnData];

? ? ? ??NSString *password = [[[NSString alloc] initWithBytes:[passwordData bytes] length:[passwordData length]?

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?encoding:NSUTF8StringEncoding] autorelease];

? ? ? ? [returnDictionary setObject:password forKey:(id)kSecValueData];

? ? }

? ?else

? ? {

? ? ? ? ? ?NSAssert(NO, @"Serious error, no matching item found in the keychain.\n");

? ? }

?? ?

? ? [passwordData release];

? ?

return returnDictionary;

}


- (void)writeToKeychain

{

? ?NSDictionary *attributes = NULL;

? ?NSMutableDictionary *updateItem = NULL;

OSStatus result;

?? ?

? ?if (SecItemCopyMatching((CFDictionaryRef)genericPasswordQuery, (CFTypeRef *)&attributes) == noErr)

? ? {

? ? ? ??updateItem = [NSMutableDictionary dictionaryWithDictionary:attributes];

? ? ? ? [updateItem setObject:[genericPasswordQuery objectForKey:(id)kSecClass] forKey:(id)kSecClass];

? ? ? ?NSMutableDictionary *tempCheck = [self dictionaryToSecItemFormat:keychainItemData];

? ? ? ? [tempCheck removeObjectForKey:(id)kSecClass];

?

#if TARGET_IPHONE_SIMULATOR

?

[tempCheck removeObjectForKey:(id)kSecAttrAccessGroup];

#endif

? ? ? ? result = SecItemUpdate((CFDictionaryRef)updateItem, (CFDictionaryRef)tempCheck);

NSAssert( result == noErr, @"Couldn't update the Keychain Item." );

? ? }

? ?else

? ? {

? ? ? ??result = SecItemAdd((CFDictionaryRef)[self dictionaryToSecItemFormat:keychainItemData], NULL);

NSAssert( result == noErr, @"Couldn't add the Keychain Item." );

? ? }

}


?

@end

PS: 1.?KeychainItemWrapper類在官方Demo里面也有,如果我復制出錯了,大家可以在上面的鏈接上下載官方Demo. ? ?2.使用時要添加Security.framework ? ?3.?尤為注意的是,UUID類下面這句代碼中group的設置方法。 ? ? KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc]

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?initWithIdentifier:@"UUID"

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?accessGroup:@"YOUR_BUNDLE_SEED.com.yourcompany.userinfo"];

? ? (1)在項目相同的目錄下創建KeychainAccessGroups.plist文件。

? ? ? ? ?


該文件的結構中最頂層的節點必須是一個名為“keychain-access-groups”的Array,并且該Array中每一項都是一個描述分組的NSString。YOUR_BUNDLE_SEED.com.yourcompany.userinfo就是要設置的組名。 ? ? ? ?(2)在項目相同的目錄下創建KeychainAccessGroups.plist文件。在Target-Build Settings-Code Signing欄下的Code Signing?Entitlements右側添加KeychainAccessGroups.plist,如下圖。 ? ? ? ? ??
到此,工作就完成了。 首次安裝程序時,打印出一個uuid,當把程序卸載后,再用getUUID獲得 uuid,打印出來的結果和之前相同。證明達到目的。 測試代碼:

??NSString * uuid= [UUID getUUID];

?NSLog(@"uuid=%@",uuid);

? 測試結果: ??uuid=19AAB430-9CB8-4325-ACC5-D7D386B68960

轉載于:https://www.cnblogs.com/hxwj/p/4828032.html

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的(绝对有用)iOS获取UUID,并使用keychain存储的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。