Last active
August 29, 2015 13:56
-
-
Save gin0606/8915166 to your computer and use it in GitHub Desktop.
iOS7以降でuniqueIdentifierを取得(生成)する。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Created by gin0606 on 2013/10/03. | |
// | |
#import <Foundation/Foundation.h> | |
@interface UIDevice (GINUniqueIdentifier) | |
- (NSString *)gin_uniqueIdentifier; | |
@end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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