如何在钥匙串iOS中保存UUID?

时间:2015-01-02 09:08:04

标签: ios uuid keychain

我是iOS开发中的新手,我想将我的应用程序UUID存储在KeyChain中所以任何时候我的应用程序UUID保持不变我在它上面做R& D并从这个站点查找代码我乱糟糟的StackOver Flow代码就像如

+(NSUUID *)persistentIdentifierForVendor
{
static NSString * const kKeyChainVendorID = @"co.cwbrn.PersistentIdentifier";
static NSString * const kKeyChainVendorIDAccessGroup = @"<AppIdentifier>.<keychain-access-group-identifier>";

// First, check NSUserDefaults so that we're not hitting the KeyChain every single time
NSString *uuidString = [[NSUserDefaults standardUserDefaults] stringForKey:kKeyChainVendorIDGroup];
BOOL vendorIDMissingFromUserDefaults = (uuidString == nil || uuidString.length == 0);

if (vendorIDMissingFromUserDefaults) {
    // Check to see if a UUID is stored in the KeyChain
    NSDictionary *query = @{
                            (__bridge id)kSecClass:             (__bridge id)kSecClassGenericPassword,
                            (__bridge id)kSecAttrAccount:       kKeyChainVendorID,
                            (__bridge id)kSecAttrService:       kKeyChainVendorID,
                            (__bridge id)kSecAttrAccessGroup:   kKeyChainVendorIDAccessGroup,
                            (__bridge id)kSecMatchLimit:        (__bridge id)kSecMatchLimitOne,
                            (__bridge id)kSecReturnAttributes:  (__bridge id)kCFBooleanTrue
                           };
    CFTypeRef attributesRef = NULL;
    OSStatus result = SecItemCopyMatching((__bridge CFDictionaryRef)query, &attributesRef);
    if (result == noErr) {
        // There is a UUID, so try to retrieve it
        NSDictionary *attributes = (__bridge_transfer NSDictionary *)attributesRef;
        NSMutableDictionary *valueQuery = [NSMutableDictionary dictionaryWithDictionary:attributes];

        [valueQuery setObject:(__bridge id)kSecClassGenericPassword  forKey:(__bridge id)kSecClass];
        [valueQuery setObject:(__bridge id)kCFBooleanTrue            forKey:(__bridge id)kSecReturnData];

        CFTypeRef passwordDataRef = NULL;
        OSStatus result = SecItemCopyMatching((__bridge CFDictionaryRef)valueQuery, &passwordDataRef);
        if (result == noErr) {
            NSData *passwordData = (__bridge_transfer NSData *)passwordDataRef;
            uuidString = [[NSString alloc] initWithBytes:[passwordData bytes]
                                                  length:[passwordData length]
                                                encoding:NSUTF8StringEncoding];
        }
    }
}

// Failed to read the UUID from the KeyChain, so create a new UUID and store it
if (uuidString == nil || uuidString.length == 0) {
    // Generate the new UIID
    CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
    uuidString = (__bridge_transfer NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuidRef);
    CFRelease(uuidRef);

    // Now store it in the KeyChain
    NSDictionary *query = @{    (__bridge id)kSecClass:             (__bridge id)kSecClassGenericPassword,
                                (__bridge id)kSecAttrAccount:       kKeyChainVendorID,
                                (__bridge id)kSecAttrService:       kKeyChainVendorID,
                                (__bridge id)kSecAttrAccessGroup:   kKeyChainVendorIDAccessGroup,
                                (__bridge id)kSecAttrLabel:         @"",
                                (__bridge id)kSecAttrDescription:   @"",
                                (__bridge id)kSecAttrAccessible:    (__bridge id)kSecAttrAccessibleAfterFirstUnlock,
                                (__bridge id)kSecValueData:         [uuidString dataUsingEncoding:NSUTF8StringEncoding]
                            };

    OSStatus result = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
    if (result != noErr) {
        NSLog(@"ERROR: Couldn't add to the Keychain. Result = %ld; Query = %@", result, query);
        return nil;
    }
}

// Save UUID to NSUserDefaults so that we can avoid the KeyChain next time
if (vendorIDMissingFromUserDefaults) {
    [[NSUserDefaults standardUserDefaults] setObject:uuidString forKey:kKeyChainVendorIDGroup];
}

return [[NSUUID alloc] initWithUUIDString:uuidString];

}

但我想知道这里使用的kKeyChainVendorIDkKeyChainVendorIDAccessGroup是什么样的

 static NSString * const kKeyChainVendorID = @"co.cwbrn.PersistentIdentifier";
static NSString * const kKeyChainVendorIDAccessGroup = @"<AppIdentifier>.<keychain-access-group-identifier>";

对于我的应用程序,我如何得到两个值,如kKeyChainVendorIDkKeyChainVendorIDAccessGroup?请给我解决方案,并在我的Xcode 5.0版本错误发生在行

 NSString *uuidString = [[NSUserDefaults standardUserDefaults] stringForKey:kKeyChainVendorIDGroup];

错误是: - 将kKeyChainVendorIDGroup替换为kKeyChainVendorID。我可以替换它然后它是工作与否请给我解决方案我的两个问题

提前致谢。并感谢nelico在堆栈溢出中发布回答。

1 个答案:

答案 0 :(得分:2)

我发布自己的答案。我从这个链接中得到答案

http://objectivecwithsuraj.blogspot.in/2014/01/unique-identifier-uuid-ios.html

我使用FDKeyChain并编写以下代码在KeyChain中保存UUID

只需定义两个字符串,如

static NSString * const KeychainItem_Service = @"FDKeychain";
static NSString * const KeychainItem_UUID = @"Local";

和Get UUID我写为

uniqueIdentifier=[self generateUUID];
-(NSString *)generateUUID {
NSString *CFUUID = nil;

if (![FDKeychain itemForKey: KeychainItem_UUID
                 forService: KeychainItem_Service
                      error: nil]) {
    CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);

    CFUUID = (NSString *)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuid));

    [FDKeychain saveItem: CFUUID
                  forKey: KeychainItem_UUID
              forService: KeychainItem_Service
                   error: nil];

} else {
    CFUUID = [FDKeychain itemForKey: KeychainItem_UUID
                         forService: KeychainItem_Service
                              error: nil];
}

return CFUUID;

}

希望对SomeOne有所帮助。如果我的答案有问题,请给我解决方案。谢谢你的回复。