【iOS/Objective-c】キーチェーンラッパー
まぁオープンソースとかでもいろいろあるんだけどさ。
ソース汚いし。
諸事情で使えないので作った。
俺が書いたらこんな短いのに。
同じ処理を3倍以上の行数で書いてるのがgithubとかにあって、あーぁってなる。
KeyChainWrapper.h
#import <Foundation/Foundation.h> /*! @class KeyChainWrapper @brief キーチェーンラッパー */ @interface KeyChainClient : NSObject /*! @brief インスタンス生成 @param classValue Class Value Constants @param accessible Attribute Key Constants */ - (id)initWithClassValue:(CFTypeRef)classValue accessible:(CFTypeRef)accessible; /*! @brief KeyChainに値を保存 @param value 値 @param key キー */ - (BOOL)saveValueToKeyChain:(id)value forKey:(NSString *)key; /*! @brief KeyChainから値を削除 @param key キー */ - (BOOL)removeValueFromKeyChainForKey:(NSString *)key; /*! @brief KeyChainから値を取得 @param key キー */ - (id)valueFromKeyChainForKey:(NSString *)key; @end
KeyChainWrapper.m
#import "KeyChainWrapper.h" @interface KeyChainWrapper() @property (nonatomic) CFTypeRef classValue; @property (nonatomic) CFTypeRef accessible; @end @implementation KeyChainWrapper - (id)init { [self doesNotRecognizeSelector:_cmd]; return nil; } - (id)initWithClassValue:(CFTypeRef)classValue accessible:(CFTypeRef)accessible { self = [super init]; if (self) { self.classValue = classValue; self.accessible = accessible; } return self; } - (BOOL)saveValueToKeyChain:(id)value forKey:(NSString *)key { [self removeValueFromKeyChainForKey:key]; NSDictionary *optional = @{ (__bridge id)kSecValueData : [NSKeyedArchiver archivedDataWithRootObject:value] }; return SecItemAdd([self keyChainAttributesForKey:key optional:optional], NULL) == noErr; } - (BOOL)removeValueFromKeyChainForKey:(NSString *)key { return SecItemDelete([self keyChainAttributesForKey:key]) == noErr; } - (id)valueFromKeyChainForKey:(NSString *)key { NSDictionary *optional = @{ (__bridge id)kSecReturnData : (__bridge id)kCFBooleanTrue, (__bridge id)kSecMatchLimit : (__bridge id)kSecMatchLimitOne }; id value; CFDataRef keyData; if (SecItemCopyMatching([self keyChainAttributesForKey:key optional:optional], (CFTypeRef *)&keyData) == noErr) { @try { value = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData]; } @catch (NSException *e) { value = nil; } @finally {} } if (keyData) CFRelease(keyData); return value; } - (CFDictionaryRef)keyChainAttributesForKey:(NSString *)key { return (__bridge CFDictionaryRef) [NSMutableDictionary dictionaryWithDictionary: @{ (__bridge id)kSecClass : (__bridge id)self.classValue, (__bridge id)kSecAttrService : key, (__bridge id)kSecAttrAccount : key, (__bridge id)kSecAttrAccessible : (__bridge id)self.accessible, }]; } - (CFDictionaryRef)keyChainAttributesForKey:(NSString *)key optional:(NSDictionary *)optional { NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary: (__bridge NSDictionary*)[self keyChainAttributesForKey:key]]; for (NSString *optionalKey in optional.allKeys) [dic setObject:optional[optionalKey] forKey:optionalKey]; return (__bridge CFDictionaryRef)dic; } @end
つかいかた!
KeyChainWrapper *keyChainWrapper = [[KeyChainWrapper alloc] initWithClassValue:kSecClassGenericPassword accessible:kSecAttrAccessibleAfterFirstUnlock]; [keyChainWrapper saveValueToKeyChain:@"sdjfhjsdfhksdfkds" forKey:@"key"]; NSLog(@"%@", [keyChainWrapper valueFromKeyChainForKey:@"key"]); [keyChainWrapper removeValueFromKeyChainForKey:@"key"];