IOS 6 UITextField Secure - Как обнаружить обратное пространство для очистки всех символов?
В iOS 6, если вы введете текст в защищенное текстовое поле, перейдите в другое текстовое поле, затем вернитесь в защищенное текстовое поле и нажмите "Backspace", все символы будут удалены. Я в порядке с этим случаем, однако, я пытаюсь включить/отключить кнопку, основанную на том, что это безопасное текстовое поле содержит в себе символы или нет. Я знаю, как определить, какие символы находятся в полях, и если обратное пространство попало, но у меня возникают проблемы с определением того, как определить, происходит ли очистка всех символов.
Это метод делегата, который я использую для получения нового текста поля, но я не могу понять, как получить новый текст (предполагая, что новый текст будет пустой строкой), если удаляется обратное пространство, которое очищает все символы.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
//returns the "new text" of the field
NSString * text = [textField.text stringByReplacingCharactersInRange:range withString:string];
}
Любая помощь очень ценится.
Спасибо!
Ответы
Ответ 1
Я использую это решение. Он не нуждается в локальных переменных и правильно устанавливает положение курсора после удаления char.
Это mashup этих решений:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (range.location > 0 && range.length == 1 && string.length == 0)
{
// Stores cursor position
UITextPosition *beginning = textField.beginningOfDocument;
UITextPosition *start = [textField positionFromPosition:beginning offset:range.location];
NSInteger cursorOffset = [textField offsetFromPosition:beginning toPosition:start] + string.length;
// Save the current text, in case iOS deletes the whole text
NSString *text = textField.text;
// Trigger deletion
[textField deleteBackward];
// iOS deleted the entire string
if (textField.text.length != text.length - 1)
{
textField.text = [text stringByReplacingCharactersInRange:range withString:string];
// Update cursor position
UITextPosition *newCursorPosition = [textField positionFromPosition:textField.beginningOfDocument offset:cursorOffset];
UITextRange *newSelectedRange = [textField textRangeFromPosition:newCursorPosition toPosition:newCursorPosition];
[textField setSelectedTextRange:newSelectedRange];
}
return NO;
}
return YES;
}
Ответ 2
Наконец-то выяснилось, что кто-то хочет посмотреть, как определить, когда обратное пространство очистит все символы безопасного UITextField:
UITextField:
self.passwordTextField
Частное свойство (инициализировано NO в init - возможно, не нужно):
self.passwordFirstCharacterAfterDidBeginEditing
Методы UITextFieldDelegate:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
//if text is blank when first editing, then first delete is just a single space delete
if([textField.text length] == 0 && self.passwordFirstCharacterAfterDidBeginEditing)
self.passwordFirstCharacterAfterDidBeginEditing = NO;
//if text is present when first editing, the first delete will result in clearing the entire password, even after typing text
if([textField.text length] > 0 && self.passwordFirstCharacterAfterDidBeginEditing && [string length] == 0 && textField == self.passwordTextField)
{
NSLog(@"Deleting all characters");
self.passwordFirstCharacterAfterDidBeginEditing = NO;
}
return YES;
}
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
if(textField == self.passwordTextField)
{
self.passwordFirstCharacterAfterDidBeginEditing = YES;
}
}
Я надеюсь, что это поможет кому-то, и я также надеюсь, что Apple просто создаст метод делегата, который вызывается, когда удаленное текстовое поле очищается удалением - это кажется большим громоздким, но оно работает.
Ответ 3
Защищенные текстовые поля очищаются при запуске редактирования на iOS6 +, независимо от того, удаляете ли вы или вводите текст. Проверка, если длина строки замены равна 0, работает, если текстовое поле очищается от обратного пространства, но досадно, что параметры диапазона и замены строки для textField:shouldChangeCharactersInRange:replacementString:
являются неправильными, если текст очищается при вводе текста. Это было мое решение:
1) Зарегистрируйтесь для уведомлений textFieldTextDidChange
.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(textFieldTextDidChange:)
name:UITextFieldTextDidChangeNotification
object:nil];
2) Повторно вызовите метод делегата textField:shouldChangeCharactersInRange:replacementString:
, если текстовое поле является безопасным и может быть очищено.
- (void)textFieldTextDidChange:(NSNotification *)notification
{
if (textField.secureTextEntry && textField.text.length <= 1) {
[self.textField.delegate textField:self.textField
shouldChangeCharactersInRange:NSMakeRange(0, textField.text.length)
replacementString:textField.text];
}
}
Ответ 4
Я столкнулся с одной и той же проблемой, я хотел обнаружить, когда backspace очистит все символы, чтобы я мог отключить некоторые другие кнопки на экране. Так я и достиг этого.
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
_checkForDelete = NO;
if (textField.isSecureTextEntry && textField.text.length > 0) {
_checkForDelete = YES;
}
return YES;
}
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (_checkForDelete && string.length == 0) {
_checkForDelete = NO;
//Do whatever you want to do in this case,
//because all the text is going to be cleared.
}
return YES
}
Это решение отличается тем, что позволяет вам действовать, когда в защищенном поле уже есть какой-то текст, и вы пытаетесь его отредактировать, а в приведенном выше ответе, вы пойдете в блок, даже если вы нажмете backspace while уже редактируя поле, которое не очистит весь текст, но удалит только один символ. Используя мой метод, вы можете выполнить действие в этом специальном случае, но оно не повлияет на собственный поток.
Ответ 5
Проводка моего альтернативного решения, так как у меня была точная проблема с OP, и я обнаружил, что мне не нужно было изменять положение курсора, подробно описанное в выбранном ответе.
Ниже приведен метод UITextFieldDelegate, я вызываю пользовательский метод делегирования didChangeValueForTextField, поскольку моя кнопка, которую я хочу включить, находится вне этого класса.
Класс, реализующий UITextFieldDelegate
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *newValue = [textField.text stringByReplacingCharactersInRange:range withString:string];
BOOL shouldReturn = YES;
if (range.location > 0 && range.length == 1 && string.length == 0){
[textField deleteBackward];
if ([textField.text isEmptyCheck]) { // Check if textField is empty
newValue = @"";
}
shouldReturn = NO;
}
if(self.delegate && [self.delegate respondsToSelector:@selector(didChangeValueForField:withNewValue:)]) {
[self.delegate didChangeValueForField:textField withNewValue:newValue];
}
return shouldReturn;
}
Ключ был обнаружен разницей между удалением одиночного символа безопасного поля и удалением одиночного символа безопасного поля, которое запускает поле clear. Обнаружение этого в указанном выше методе делегата было необходимо.
Клавиша, содержащая кнопку для включения
- (void)didChangeValueForField:(UITextField *)textField withNewValue:(NSString *)value {
// Update values used to validate/invalidate the button.
// I updated a separate model here.
// Enable button based on validity
BOOL isEnabled = [self allFieldsValid]; // Check all field values that contribute to the button being enabled.
self.myButton.enabled = isEnabled;
}
Ответ 6
Принятое решение не включает кнопку. Это фактически изменяет поведение backspace в защищенном текстовом поле.
Это решение Swift решает вопрос, правильно информируя делегата о фактической строке, которая будет установлена в текстовом поле, в том числе при нажатии на обратное пространство. Затем этот делегат может принять решение.
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
var shouldChange = true
if let text = textField.text {
let oldText = text.copy()
var resultString = (text as NSString).stringByReplacingCharactersInRange(range, withString: string) as NSString
let inputString = string as NSString
if range.location > 0 && range.length == 1 && inputString.length == 0 {//Backspace pressed
textField.deleteBackward()
shouldChange = false
if let updatedText = textField.text as NSString? {
if updatedText.length != oldText.length - 1 {
resultString = ""
}
}
}
self.delegate?.willChangeTextForCell(self, string: resultString as String)
}
return shouldChange
}
Ответ 7
Свифта-3
let text = textField.text
if string.length == 0{
textField.deleteBackward()
if textField.text?.length != (text?.length)! - 1 {
//deleted whole word
}
return false // this is important
}
Ответ 8
swift3.0 - он работает.
func textField (_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) → Bool {
if textField == passwordTextfield {
if range.location > 0 && range.length == 1 && string.characters.count == 0 {
if let textString = textField.text {
// iOS is trying to delete the entire string
let index = textString.index(textString.endIndex, offsetBy: -1)
textField.text = textString.substring(to: index)
return false
}
}else if range.location == 0 {
return true
}else {
if let textString = textField.text {
textField.text = textString + string
return false
}
}
}
return true
}