Я знаю, что это было несколько месяцев назад, но у меня была та же самая проблема, и это было больно, поэтому я решил поделиться.Я решил это, добавив следующую строку:
[self.keychainItemWrapper setObject:@"MY_APP_CREDENTIALS" forKey:(id)kSecAttrService];
//@"MY_APP_CREDENTIALS" can be any string.
Я нашел эту запись в блоге очень полезной: «В терминах базы данных вы можете подумать, что они являются уникальным индексом для двух атрибутов kSecAttrAccount, kSecAttrService, требующих комбинации этихдва атрибута, которые должны быть уникальными для каждой записи в цепочке для ключей. "(из http://useyourloaf.com/blog/2010/4/28/keychain-duplicate-item-when-adding-password.html).
Кроме того, в примере проекта Apple, использующего этот код, они создают экземпляр KeychainItemWrapper в делегате приложения. Я не знаю, если это необходимо, но мне нравится следовать их примерам настолько близко, насколько это возможно:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
//there will be some standard code here.
KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MY_APP_CREDENTIALS" accessGroup:nil];
self.keychainWrapper = wrapper;
[self.keychainWrapper setObject:@"MYOBJECT" forKey:(id)kSecAttrService];
[wrapper release];
}
Я думаю, что это ошибка в коде оболочки. Логика в основном говорит: «Эта запись уже существует? Нет, это не так. Хорошо, я добавлю ее. Ой, вы можетене добавляйте его, потому что он уже есть. "
Вам также может понадобиться установить kSecAttrAccount; я никогда не пробовал его, не устанавливая также это значение, поскольку он предназначен для сохранения имени пользователя, которое идет с паролем:
[self.wrapper setObject:txtUserName.text forKey:(id)kSecAttrAccount];