你好,歡迎來到IOS教程網

 Ios教程網 >> IOS使用技巧 >> IOS7技巧 >> iOS獲取UUID,並使用keychain存儲的代碼

iOS獲取UUID,並使用keychain存儲的代碼

編輯:IOS7技巧
UUID是蘋果手機開發者在測試時必須要綁定的一個東西,只有綁定了UUID才可以正常的在測試手機中安裝我們的ios的app了,下面來看看。

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

 
給大家兩個類:


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)kSecClassGenericPassword forKey:(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)kSecClassGenericPassword forKey:(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文件。

 

         (絕對有用)iOS獲取UUID,並使用keychain存儲

 

iOS開發,UUID   該文件的結構中最頂層的節點必須是一個名為“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,如下圖。           (絕對有用)iOS獲取UUID,並使用keychain存儲   iOS開發,UUID  到此,工作就完成了。    首次安裝程序時,打印出一個uuid,當把程序卸載後,再用getUUID獲得 uuid,打印出來的結果和之前相同。證明達到目的。  

 

測試代碼:

NSString * uuid= [UUID getUUID];
  NSLog(@"uuid=%@",uuid);
  測試結果:

  uuid=19AAB430-9CB8-4325-ACC5-D7D386B68960

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved