Skip to content

Instantly share code, notes, and snippets.

@gin0606
Last active August 29, 2015 13:56
Show Gist options
  • Save gin0606/8915166 to your computer and use it in GitHub Desktop.
Save gin0606/8915166 to your computer and use it in GitHub Desktop.
iOS7以降でuniqueIdentifierを取得(生成)する。
//
// Created by gin0606 on 2013/10/03.
//
#import <Foundation/Foundation.h>
@interface UIDevice (GINUniqueIdentifier)
- (NSString *)gin_uniqueIdentifier;
@end
//
// Created by gin0606 on 2013/10/03.
//
#import "UIDevice+GINUniqueIdentifier.h"
// 参考 http://qiita.com/items/ace0caf4b909c785836f
@implementation UIDevice (GINUniqueIdentifier)
- (NSString *)gin_bundleIdentifier {
return [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *) kCFBundleIdentifierKey];
}
- (NSString *)gin_uuidKey {
return [NSString stringWithFormat:@"%@.keychain.uniqueIdentifier.key", [self gin_bundleIdentifier]];
}
- (NSString *)gin_userDefaultsKey{
return [NSString stringWithFormat:@"%@.uniqueIdentifier.key", [self gin_bundleIdentifier]];
}
- (NSString *)gin_uniqueIdentifier {
NSString *uuidString = [self gin_loadUUIDFromUserDefaults];
// UserDefaultsに無かったらキーチェーンから探す
if (!uuidString) {
uuidString = [self gin_findUUIDFromKeyChain];
}
// キーチェーンにも無かったら生成する
if (!uuidString) {
uuidString = [self gin_generateNewUUID];
}
//UUIDをUserDefaultに保存する
[[NSUserDefaults standardUserDefaults] setObject:uuidString forKey:[self gin_userDefaultsKey]];
[[NSUserDefaults standardUserDefaults] synchronize];
return uuidString;
}
- (NSString *)gin_loadUUIDFromUserDefaults {
return [[NSUserDefaults standardUserDefaults] stringForKey:[self gin_userDefaultsKey]];
}
- (NSString *)gin_findUUIDFromKeyChain {
NSString *uuidString;
NSDictionary *query = @{
(__bridge id) kSecClass : (__bridge id) kSecClassGenericPassword,
(__bridge id) kSecAttrGeneric : [self gin_uuidKey],
(__bridge id) kSecAttrAccount : [self gin_uuidKey],
(__bridge id) kSecAttrService : [[NSBundle mainBundle] bundleIdentifier],
(__bridge id) kSecMatchLimit : (__bridge id) kSecMatchLimitOne,
(__bridge id) kSecReturnAttributes : (__bridge id) kCFBooleanTrue,
};
CFTypeRef attributesRef;
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;
OSStatus res = SecItemCopyMatching((__bridge CFDictionaryRef) valueQuery, &passwordDataRef);
if (res == 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];
}
}
return uuidString;
}
- (NSString *)gin_generateNewUUID {
CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
NSString *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)];
NSMutableDictionary *query = [@{
(__bridge id) kSecClass : (__bridge id) kSecClassGenericPassword,
(__bridge id) kSecAttrGeneric : [self gin_uuidKey],
(__bridge id) kSecAttrAccount : [self gin_uuidKey],
(__bridge id) kSecAttrService : [[NSBundle mainBundle] bundleIdentifier],
(__bridge id) kSecAttrLabel : @"",
(__bridge id) kSecAttrDescription : @"",
} mutableCopy];
[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;
}
return uuidString;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment