UITextField with secure entry, always getting cleared before editing
Set,
textField.clearsOnBeginEditing = NO;
Note: This won't work if secureTextEntry = YES. It seems, by default, iOS clears the text of secure entry text fields before editing, no matter clearsOnBeginEditing is YES or NO.
If you don't want the field to clear, even when secureTextEntry = YES, use:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *updatedString = [textField.text stringByReplacingCharactersInRange:range withString:string];
textField.text = updatedString;
return NO;
}
I encountered a similar issue when adding show/hide password text functionality to a sign-up view.
If you're using Swift 3, give this subclass a go.
class PasswordTextField: UITextField {
override var isSecureTextEntry: Bool {
didSet {
if isFirstResponder {
_ = becomeFirstResponder()
}
}
}
override func becomeFirstResponder() -> Bool {
let success = super.becomeFirstResponder()
if isSecureTextEntry, let text = self.text {
self.text?.removeAll()
insertText(text)
}
return success
}
}
Why does this work?
TL;DR: if you're editing the field while toggling isSecureTextEntry
, make sure you call becomeFirstResponder
.
Toggling the value of isSecureTextEntry
works fine until the user edits the textfield - the textfield clears before placing the new character(s). This tentative clearing seems to happen during the becomeFirstResponder
call of UITextField
. If this call is combined with the deleteBackward
/insertText
trick (as demonstrated in answers by @Aleksey and @dwsolberg), the input text is preserved, seemingly canceling the tentative clearing.
However, when the value of isSecureTextEntry
changes while the textfield is the first responder (e.g., the user types their password, toggles a 'show password' button back and forth, then continues typing), the textfield will reset as usual.
To preserve the input text in this scenario, this subclass triggers becomeFirstResponder
only if the textfield was the first responder. This step seems to be missing in other answers.
Thanks @Patrick Ridd for the correction!