まぁオープンソースとかでもいろいろあるんだけどさ。
ソース汚いし。
諸事情で使えないので作った。
俺が書いたらこんな短いのに。
同じ処理を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"];