iOS KeychainItemWrapper не обновляется

Я только что нашел интересную проблему с моим приложением. В приложении я сохраняю имя пользователя и пароль пользователя в цепочке для ключей.

keychainWrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyLoginPassword" accessGroup:nil];

[keychainWrapper setObject:usernameField.text forKey:(id)kSecAttrAccount];
[keychainWrapper setObject:passwordField.text forKey:(id)kSecValueData];

Когда этот код запускается в Debug, он, кажется, работает просто отлично. Он обновляется каждый раз, и позже я могу получить элементы из цепочки для ключей. Однако когда он запускается в Distribution, цепочка для ключей никогда не обновляется. Я подтвердил, что да, эти строки кода встречаются в обеих сборках. Я использую Xcode 4.2 с iOS5 SDK и запускаю приложение на iPad 2 с установленной iOS5.

2 ответа

Решение

У меня тоже была эта проблема, и мне понадобилось вечно, чтобы выяснить,

Существует версия "KeychainWrapper", которая имеет SecItemUpdate в NSAssert (среди прочего).

Кто бы это ни сделал, это придурок!, при сборке для выпуска / распространения каждый NSAssert обнуляется, что означает, что код даже не запускается.

Например:

NSAssert(SecItemUpdate((CFDictionaryRef)updateItem, (CFDictionaryRef)tempCheck), @"Couldn't update the Keychain Item." );

Должен стать

OSStatus status = SecItemUpdate((CFDictionaryRef)updateItem, (CFDictionaryRef)tempCheck);
NSAssert(status == noErr, @"Couldn't update the Keychain Item." );

Обратите внимание, как фактическое SecItemUpdate перемещается за пределы NSAssert, и вместо этого проверяется результат

Важное примечание: Попытка обновить значение для kSecValueData без указания значения для kSecAttrAccount также приведет к сбою подтверждения. Итак, если вы хотите сохранить одну строку конфиденциальных данных (например, список номеров кредитных карт), обязательно сохраните некоторый текст "имени учетной записи" в атрибуте kSecAttrAccount, например так:

static NSString* kCardListXML = @"cardListXML";
static NSString* cardListAccountName = @"cardListAccount";

-(void)setCardListXML:(NSString*)xml {
  KeychainItemWrapper* wrapper =
    [[KeychainItemWrapper alloc] initWithIdentifier:kCardListXML accessGroup:nil];
  [wrapper setObject:cardListAccountName forKey:(id)CFBridgingRelease(kSecAttrAccount)];
  [wrapper setObject:xml forKey:(id)CFBridgingRelease(kSecValueData)];
}    

-(NSString*)getCardListXML {
  KeychainItemWrapper* wrapper =
    [[KeychainItemWrapper alloc] initWithIdentifier:kCardListXML accessGroup:nil];
  [wrapper setObject:cardListAccountName forKey:(id)CFBridgingRelease(kSecAttrAccount)];
  return [wrapper objectForKey:CFBridgingRelease(kSecValueData)];
}

Когда вы включаете

keychainWrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyLoginPassword" accessGroup:nil];

[keychainWrapper setObject:usernameField.text forKey:(id)kSecAttrAccount];
[keychainWrapper setObject:passwordField.text forKey:(id)kSecValueData];

Вы также должны были включить

[keychainWrapper setObject:@"Myappstring" forKey: (id)kSecAttrService];

Или я получаю ошибку "SIGABRT". (Myappstring) - это строка, определяющая ваше приложение.

Может быть, я что-то упустил, это нужно сделать хотя бы один раз.

Другие вопросы по тегам