UITextField с защищенным входом, всегда очищается перед редактированием - PullRequest
33 голосов
/ 05 сентября 2011

У меня странная проблема, из-за которой мой UITextField, который содержит защищенную запись, всегда очищается, когда я пытаюсь ее отредактировать. Я добавил 3 символа в поле, перешел в другое поле и вернулся, курсор находится в позиции 4-го символа, но когда я пытаюсь добавить другой символ, весь текст в поле очищается новым символом. У меня «Очистить, когда редактирование начинается» снят в перо. Так в чем же проблема? Если я удаляю свойство защищенной записи, все работает нормально, так это свойство текстовых полей защищенной записи? Есть ли способ предотвратить такое поведение?

Ответы [ 23 ]

1 голос
/ 17 августа 2016

После игры с решением от @malex я пришел к этой Swift версии:

1) Не забудьте сделать свой контроллер вида UITextFieldDelegate:

class LoginViewController: UIViewController, UITextFieldDelegate {
...
}

override func viewDidLoad() {
   super.viewDidLoad()
   textfieldPassword.delegate = self
}

2) используйте это:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if let start: UITextPosition = textField.positionFromPosition(textField.beginningOfDocument, offset: range.location),
       let end: UITextPosition = textField.positionFromPosition(start, offset: range.length),
       let textRange: UITextRange = textField.textRangeFromPosition(start, toPosition: end) {
           textField.replaceRange(textRange, withText: string)
    }
    return false
}

... и если вы делаете это для функции «показать / скрыть пароль», вам, скорее всего, потребуется сохранить и восстановить позицию каретки, когда вы включите secureTextEntry/ выкл.Вот как (сделать это внутри метода переключения):

var startPosition: UITextPosition?
var endPosition: UITextPosition?

// Remember the place where cursor was placed before switching secureTextEntry
if let selectedRange = textfieldPassword.selectedTextRange {
   startPosition = selectedRange.start
   endPosition = selectedRange.end
}

...

// After secureTextEntry has been changed
if let start = startPosition {
   // Restoring cursor position
   textfieldPassword.selectedTextRange = textfieldPassword.textRangeFromPosition(start, toPosition: start)
   if let end = endPosition {
       // Restoring selection (if there was any)
       textfieldPassword.selectedTextRange = textfield_password.textRangeFromPosition(start, toPosition: end)
       }
}
1 голос
/ 03 апреля 2017

Это быстрый код из моего проекта, проверенный и имеющий дело с изменениями возврата и безопасного входа false / true

// получить пользовательский ввод и вызвать методы проверки

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    if (textField == passwordTextFields) {

        let newString = (textField.text! as NSString).replacingCharacters(in: range, with: string)

        // prevent backspace clearing the password
        if (range.location > 0 && range.length == 1 && string.characters.count == 0) {
            // iOS is trying to delete the entire string
            textField.text = newString
            choosPaswwordPresenter.validatePasword(text: newString as String)

            return false
        }

        // prevent typing clearing the pass
        if range.location == textField.text?.characters.count {
            textField.text = newString
            choosPaswwordPresenter.validatePasword(text: newString as String)

            return false
        }

        choosPaswwordPresenter.validatePasword(text: newString as String)
    }

    return true
}
1 голос
/ 16 декабря 2016

Мы решили это, основываясь на ответе dwsolberg с двумя исправлениями:

  • текст пароля был дублирован при нажатии на уже выделенное поле пароля
  • последнеесимвол пароля был обнаружен при нажатии в поле пароля
  • deleteBackward и insertText, чтобы вызвать событие измененного значения, чтобы оно было запущено

Итак, мы придумали это (Swift2.3):

class PasswordTextField: UITextField {

    override func becomeFirstResponder() -> Bool {
        guard !isFirstResponder() else {
            return true
        }
        guard super.becomeFirstResponder() else {
            return false
        }
        guard secureTextEntry, let text = self.text where !text.isEmpty else {
            return true
        }

        self.text = ""
        self.text = text

        // make sure that last character is not revealed
        secureTextEntry = false
        secureTextEntry = true

        return true
    }
}
0 голосов
/ 06 февраля 2019

IOS 12, Swift 4

  • Не отображает последний символ, когда текстовое поле снова становится первым респондентом.
  • Не дублирует существующий текст при повторном касании текстового поля.

Если вы хотите использовать это решение не только с безопасным вводом текста, добавьте проверку isSecureTextEntry.

class PasswordTextField: UITextField {
    override func becomeFirstResponder() -> Bool {
        let wasFirstResponder = isFirstResponder
        let success = super.becomeFirstResponder()
        if !wasFirstResponder, let text = self.text {
            insertText("\(text)+")
            deleteBackward()
        }
        return success
    }
}
0 голосов
/ 28 ноября 2018

когда мой проект обновится до iOS 12.1 и возникнет эта проблема. Это мое решение по этому поводу. Все в порядке.



    - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
        NSMutableString *checkString = [textField.text mutableCopy];
        [checkString replaceCharactersInRange:range withString:string];
        textField.text = checkString;
        NSRange selectedRange = NSMakeRange(range.location + string.length, 0);
        UITextPosition* from = [textField positionFromPosition:textField.beginningOfDocument offset:selectedRange.location];
        UITextPosition* to = [textField positionFromPosition:from offset:selectedRange.length];
        textField.selectedTextRange = [textField textRangeFromPosition:from toPosition:to];
        [textField sendActionsForControlEvents:UIControlEventEditingChanged];
        return NO;
    }

0 голосов
/ 23 мая 2018

Я использовал ответ @EmptyStack textField.clearsOnBeginEditing = NO; в своем текстовом поле для пароля passwordTextField.secureTextEntry = YES;, но это не сработало в iOS11 SDK с Xcode 9.3, поэтому я выполнил следующий код для достижения.На самом деле я хочу сохранить текст (в текстовом поле), если пользователь переключается между различными полями.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (textField.tag == 2) {
        if ([string isEqualToString:@""] && textField.text.length >= 1) {
            textField.text = [textField.text substringToIndex:[textField.text length] - 1];
        } else{
            textField.text = [NSString stringWithFormat:@"%@%@",textField.text,string];
        }
        return false;
    } else {
        return true;
    }
}

Я вернул false в shouldChangeCharactersInRange и манипулировал, как я хочу, этот код также работает, если пользователь нажимает кнопку удаления, чтобы удалить символ.

0 голосов
/ 10 мая 2012

Сохранить текст, введенный в свойство. Например:

NSString *_password;

А потом в делегате:

textFieldDidBeginEditing:(UITextField *)textField
assign textField.text = _password;
0 голосов
/ 07 сентября 2017

Мне нужно было настроить решение @ thomas-verbeek, добавив свойство, которое касается случая, когда пользователь пытается вставить любой текст в поле (текст был продублирован)

class PasswordTextField: UITextField {

    private var barier = true

    override var isSecureTextEntry: Bool {
        didSet {
            if isFirstResponder {
                _ = becomeFirstResponder()
            }
        }
    }

    override func becomeFirstResponder() -> Bool {
        let success = super.becomeFirstResponder()
        if isSecureTextEntry, let text = self.text, barier {
            deleteBackward()
            insertText(text)
        }
        barier = !isSecureTextEntry
        return success
    }

}
0 голосов
/ 04 апреля 2013

Я понимаю, что это немного устарело, но в iOS 6 «текст» UITextField теперь по умолчанию «Приписывается» в Интерфейсном Разработчике. Переключение на «Обычный», как это было в iOS 5, устраняет эту проблему.

Также опубликовал этот же ответ в вопросе, связанном @Craig.

0 голосов
/ 08 июля 2013

У меня была такая же проблема, но я получил решение;

-(BOOL)textFieldShouldReturn:(UITextField *)textField
    {

        if(textField==self.m_passwordField)
        {
            text=self.m_passwordField.text;  
        }

        [textField resignFirstResponder];

        if(textField==self.m_passwordField)
        {
            self.m_passwordField.text=text;
        }
        return YES;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...