У меня тоже была эта проблема, и мне потребовалось целую вечность, чтобы выяснить
Существует версия "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)];
}