接下來工作的代碼可以讓你維護綁在主「鑰匙」(這裏的電子郵件地址可能是在您的應用程序的任何主要標識符)數據的詞典。
其他鍵被存儲在任意大小的字典中,並被放置在什麼將是「密碼」keyChain對象。
首先,我把這個在我AppDelegate.h文件的底部:
#define kEmail @"email"
#define kPassword @"pass"
#define kSomeOtherItemA @"a_item"
#define kSomeOtherItemB @"b_item"
@interface AppDelegate (Keychain)
- (NSDictionary *)keychainDictionary; // current keyChain dictionary
- (void)eraseKeychain; // total wipe it
- (void)erasePassword; // wipe the password
@end
,你認爲合適,您可以在這裏添加特殊的方法。通過放置這是AppDelegate.h文件,任何其他導入該文件的類都可以使用這些方法。如果你想它的私人它移到您的AppDelegate.m文件
這正好在你的AppDelegate.m文件,往上頂:
@interface AppDelegate (KeychainPrivate)
- (void)updateKeychainItem:(NSString *)item forKey:(NSString *)key; //the password, or itemA, or itemB
- (id)keychainItemForKey:(NSString *)key; // the password, itemA, itemB, ...
@end
這可以去AppDelegate.m的底部或在一個單獨的文件:
static char *kcIdentifier = "foo"; // use any string you want instead of "foo"
@implementation AppDelegate (Keychain)
- (KeychainItemWrapper *)keyChainItemWrapper
{
static dispatch_once_t pred;
static KeychainItemWrapper *kciw;
dispatch_once(&pred,^
{
kciw = [[KeychainItemWrapper alloc] initWithIdentifier:kcIdentifier accessGroup:nil];
});
return kciw;
}
- (NSDictionary *)keychainDictionary
{
NSMutableDictionary *mDict = [NSMutableDictionary dictionaryWithCapacity:3];
KeychainItemWrapper *kcItem = [self keyChainItemWrapper];
NSString *emailAddr = [kcItem objectForKey:(__bridge id)kSecAttrAccount];
if([emailAddr length]) {
NSData *data = [kcItem objectForKey:(__bridge id)kSecValueData];
if([data length]) {
NSKeyedUnarchiver *kua = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
NSDictionary *dict = [kua decodeObject];
[kua finishDecoding];
[mDict addEntriesFromDictionary:dict];
}
mDict[kEmail] = emailAddr; // last in case it got in the dictionary somehow
}
return mDict;
}
- (void)eraseKeychain
{
KeychainItemWrapper *kcItem = [self keyChainItemWrapper];
[kcItem resetKeychainItem];
}
- (void)erasePassword
{
[self updateKeychainItem:@"" forKey:kPassword];
}
@end
@implementation AppDelegate (KeychainPrivate)
- (void)updateKeychainItem:(NSString *)item forKey:(NSString *)key
{
KeychainItemWrapper *kcItem = [self keyChainItemWrapper];
// NSLog(@"SET KC key=%@ ITEM %@", key, item);
// NSLog(@"CURRENT KEYCHAIN: %@", [self keychainDictionary]);
if([key isEqualToString:kEmail]) {
NSString *emailAddr = [kcItem objectForKey:(__bridge id)kSecAttrAccount];
if(![emailAddr isEqualToString:item]) {
[kcItem setObject:item forKey:(__bridge id)kSecAttrAccount];
// NSLog(@"SET KC Account ITEM %@", item);
}
// NSLog(@"KC Account ITEM %@ ALREADY SET", item);
} else {
NSData *data = [kcItem objectForKey:(__bridge id)kSecValueData];
//NSLog(@"KC get DATA len=%d", [data length]);
NSDictionary *dict;
if([data length]) {
NSKeyedUnarchiver *kua = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
dict = [kua decodeObject];
[kua finishDecoding];
} else {
dict = [NSDictionary dictionary];
}
//NSLog(@"KC OLD DICT %@", dict);
if(![item isEqualToString:dict[key]]) {
//NSLog(@"KC DATA NOT EQUAL");
NSMutableDictionary *mDict = [NSMutableDictionary dictionaryWithDictionary:dict];
mDict[key] = item;
NSMutableData *tmpData = [NSMutableData dataWithCapacity:256];
NSKeyedArchiver *ka = [[NSKeyedArchiver alloc] initForWritingWithMutableData:tmpData];
[ka encodeObject:mDict];
[ka finishEncoding];
//NSLog(@"KC ENCODE MDICT %@", mDict);
[kcItem setObject:tmpData forKey:(__bridge id)kSecValueData];
//NSLog(@"SET KC DATA LEN=%d", [tmpData length]);
}
}
//NSLog(@"JUST UPDATED KEYCHAIN KEY=%@ val=%@ read dict back=%@", key, item, [self keychainDictionary]);
}
- (id)keychainItemForKey:(NSString *)key
{
NSDictionary *dict = [self keychainDictionary];
return dict[key];
}
@end
您還需要KeyChainItemWrapper類。你可以得到一個ARCified並稍作修改(以便處理字典)KeyChainItemWrapper version。你真的可以使用任何你想要的KeyChainWrapper文件,但需要做出這種改變(這是蘋果的代碼,唯一的變化比ARCifying它其他):
// Default data for keychain item.
#ifndef PASSWORD_USES_DATA
[keychainItemData setObject:@"" forKey:(__bridge id)kSecValueData];
#else
[keychainItemData setObject:[NSData data] forKey:(__bridge id)kSecValueData];
#endif
正如你所看到的,有很多日誌消息,你的如果你願意,可以取消註釋以看到它在行動中。
此代碼被用於航運應用程序。
你的代碼應工作 - 你確定你的字典裏'object'真正保存的數據在你寫信給鑰匙鏈的那一刻。 –
是的,我在應用程序級別使用相同的變量,但我需要移動鑰匙串。它真的持有價值。這應該是其他問題。 – astuter
您是否在設置它們之後嘗試使用您的代碼來檢索值? – AncAinu