LoginSignup
47
45

More than 5 years have passed since last update.

UUIDの取得、保存方法

Last updated at Posted at 2013-08-06

UUIDが既にある場合は存在するUUIDを返します。
ない場合は新たに生成したUUIDを返します。

DataStoreではUserDefaultにuuidを保存しています。
ここは実装に合わせて変更して大丈夫です。

キーチェーンはiTunesにバックアップされない為、機種変更でデータが消えてしまうのでUserDefaultに保存しています。

キーチェーンに保存しなければアプリを消した時にUserDefaultのデータは消えてしまうのでUserDefaultとキーチェーンの両方に値を保存しています。


static NSString * const UUID_Key = @"hoge";

+ (NSString*)getUUID {
    NSString *uuidString = nil;

    //まずはUserDefaultにUUIDがあるか調べてみる
    DataStore* dataStore = [DataStore instance];
    if (dataStore.baseData.uuid) {
        uuidString = dataStore.baseData.uuid;
        NSLog(@"UserDefaultにUUIDがあった場合 %@", uuidString);
    }
    //ない場合はキーチェーンから探す
    else {
        NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:
                               (__bridge id)kSecClassGenericPassword,   (__bridge id)kSecClass,
                               UUID_Key,                  (__bridge id)kSecAttrGeneric,
                               UUID_Key,                  (__bridge id)kSecAttrAccount,
                               [[NSBundle mainBundle] bundleIdentifier],(__bridge id)kSecAttrService,
                               (__bridge id)kSecMatchLimitOne,          (__bridge id)kSecMatchLimit,
                               (__bridge id)kCFBooleanTrue,             (__bridge id)kSecReturnAttributes,
                               nil];
        CFTypeRef attributesRef = NULL;
        OSStatus result = SecItemCopyMatching((__bridge CFDictionaryRef)query, &attributesRef);
        if (result == noErr) {
            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;
                // Assume the stored data is a UTF-8 string.
                uuidString = [[NSString alloc] initWithBytes:[passwordData bytes]
                                                      length:[passwordData length]
                                                    encoding:NSUTF8StringEncoding];
            }
        }
        NSLog(@"UserDefaultにUUIDはない場合 %@", uuidString);
    }

    if (uuidString == nil) {

        // Generate the new UIID
        CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
        uuidString = (__bridge_transfer NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuidRef);
        CFRelease(uuidRef);

        //以下はuuidが00000000-0000-0000-0000-000000000000になってしまう可能性があるので使わない
        //id identifier = [[UIDevice currentDevice] performSelector:@selector(identifierForVendor)];
        //uuidString = [identifier performSelector:@selector(UUIDString)];

        // UIID must be persistent even if the application is removed from devices
        // Use keychain as a storage
        NSMutableDictionary *query = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                      (__bridge id)kSecClassGenericPassword,    (__bridge id)kSecClass,
                                      UUID_Key,                   (__bridge id)kSecAttrGeneric,
                                      UUID_Key,                   (__bridge id)kSecAttrAccount,
                                      [[NSBundle mainBundle] bundleIdentifier], (__bridge id)kSecAttrService,
                                      @"",                                      (__bridge id)kSecAttrLabel,
                                      @"",                                      (__bridge id)kSecAttrDescription,
                                      nil];

        if ([[[UIDevice currentDevice] systemVersion] floatValue] < 4) {
            // kSecAttrAccessible is iOS 4 or later only
            // Current device is running on iOS 3.X, do nothing here
        } else {
            // Set kSecAttrAccessibleAfterFirstUnlock so that background applications are able to access this key.
            // Keys defined as kSecAttrAccessibleAfterFirstUnlock will be migrated to the new devices/installations via encrypted backups.
            // If you want different UIID per device, use kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly instead.
            // Keep in mind that keys defined as kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly will be removed after restoring from a backup.
            [query setObject:(__bridge id)kSecAttrAccessibleAfterFirstUnlock forKey:(__bridge id)kSecAttrAccessible];
        }
        [query setObject:[uuidString dataUsingEncoding:NSUTF8StringEncoding] forKey:(__bridge id)kSecValueData];

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

    //UUIDをUserDefaultに保存する
    dataStore.baseData.uuid = uuidString;
    [dataStore saveDatas];

    return uuidString;
}
47
45
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47
45