3

There two UITextField (email, password) in the Login/SIgnup controllers in my code (here is the example), so that users obviously could insert login/password to register/log in.

In the method shouldChangeCharactersIn I check the data inserted by user and afterwards execute method loginButtonChangeState(), that activates the login button, in case data inserted are correct:

  1. Email: should be an email, checked with RegEx.
  2. Password: Should be at least 6 characters in length

Here is the content of the method:

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

        if let text = textField.text,
            let textRange = Range(range, in: text) {
            let updatedText = text.replacingCharacters(in: textRange, with: string)

            switch textField {
                case _ where textField.isIdentical(with: email) : state[textField] = chekMail(for: updatedText)
                case _ where textField.isIdentical(with: password) : state[textField] = chekPass(for: updatedText)
                default: break
            }

             loginButtonChangeState()

            print("shouldChangeCharactersIn: textField.text:\(text), replacementString: \(string)")
        }
        return true
    }

This code works well, but the following sequence of actions breaks it, and login button keeps active.

  1. Enter Email , e.g. t@t.com
  2. Than enter password, e.g. 123456
  3. Login button – becomes active
  4. tap/go to the address field again
  5. tap/go back to the password field
  6. tap on the keyboard backspace button à login button keeps active though it should have become inactive.

The reason, why it keeps active, is because after taping backspace shouldChangeCharactersIn method transfers old content of the UITextField, which can be seen in the console log

shouldChangeCharactersIn: textField.text:, replacementString: t
shouldChangeCharactersIn: textField.text:t, replacementString: @
shouldChangeCharactersIn: textField.text:t@, replacementString: t
shouldChangeCharactersIn: textField.text:t@t, replacementString: .
shouldChangeCharactersIn: textField.text:t@t., replacementString: c
shouldChangeCharactersIn: textField.text:t@t.c, replacementString: o
shouldChangeCharactersIn: textField.text:t@t.co, replacementString: m
shouldChangeCharactersIn: textField.text:, replacementString: 1
shouldChangeCharactersIn: textField.text:1, replacementString: 2
shouldChangeCharactersIn: textField.text:12, replacementString: 3
shouldChangeCharactersIn: textField.text:123, replacementString: 4
shouldChangeCharactersIn: textField.text:1234, replacementString: 5
shouldChangeCharactersIn: textField.text:12345, replacementString: 6
shouldChangeCharactersIn: textField.text:123456, replacementString:

In this row "shouldChangeCharactersIn: textField.text:123456, replacementString: " it is seen, that replacementString is "space sighn", but textField.text still contains "123456".

Video can be seen here: https://github.com/AdAvAn/ShouldChangeCharactersInRange/raw/master/shouldChangeCharactersIn.gif

QUESTION:

How can I correct the work of the method so that “Log In” button become inactive after taping backspace on keyboard (Ideally without clearing the content of the password UITextField)?

UDP: 25.03.18

This problem only occurs for fields that have the isSecureTextEntry parameter true.

So far I have not found a more beautiful solution, except to set password.clearsOnBeginEditing = true. This allows you to clear the contents of the password field each time it triggers func textFieldDidBeginEditing (_ textField: UITextField).

adnv
  • 101
  • 2
  • 6
  • 1
    Could you just try replacing your logic with `let existingText = textField.text as NSString? let changedText = existingText?.replacingCharacters(in: range, with: string)` – user1046037 Mar 21 '18 at 16:32
  • The problem is that at the moment of pressing the space textField.text contains the previous value. Your code will simply add a space to the end of the line. In my method there is its analog. let textRange = Range (range, in: text) {              let updatedText = text.replacingCharacters (in: textRange, with: string) – adnv Mar 22 '18 at 06:38

1 Answers1

5

There is not much I did, just removed some of your lines. The updatedText should now reflect the current text of the textfield correctly, no matter whether you delete a character or add one. If your code still does not work then you got to check your switch statement and check methods.

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

    let previousText:NSString = textField.text! as NSString
    let updatedText = previousText.replacingCharacters(in: range, with: string)
    print("updatedText > ", updatedText)

   //the rest of your code

    return true
}

I hope this helps.

BCI
  • 465
  • 6
  • 19
  • I added your code to my test project (https://github.com/AdAvAn/ShouldChangeCharactersInRange), the result did not change :(. updatedText> 1 updatedText> 12 updatedText> 123 updatedText> 1234 updatedText> 12345 updatedText> 123456 updatedText> 123456 – adnv Mar 23 '18 at 16:12
  • Thank you, it helps me alot – A. Trejo Aug 10 '18 at 21:47
  • @BCI Thanks and upvote this is what I am looking for – Hattori Hanzō Jun 04 '20 at 10:11