4

I am using UITextView and implemented the delegate function

var count = 0
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    print(text)
    count += 1
    print(count)
    return true
}

sample

enter image description here

When i select the predictive text from the Keyboard, shouldChangeTextInRange delegate is calling twice.

  1. Why this delegate calling twice?
  2. Why this happening with predictive text alone
Suresh
  • 1,199
  • 2
  • 12
  • 36
  • Are you trying to count the number of characters? If so, that won't work, because deleting one character will increase the number instead of decreasing it – redent84 Jan 13 '17 at 13:22
  • count is to see how many times the delegate get called – Suresh Jan 13 '17 at 13:23
  • What's the issue then? Why is being called twice a problem in your application? – redent84 Jan 13 '17 at 13:26
  • When i select any word from the predictive text(auto suggestion text above keyboard) delegate is calling twice. Wanted to control that. If it get called twice my logic placed inside the shouldTextChangeInRange wont work as expected – Suresh Jan 13 '17 at 13:29
  • I am not sure it will work or not for you But when you selected word from the predicted word at that time first it set a word then append a space that's the reason it's calling delegate twice. so the simple solution is to check that inserted character count after removing white spaces. Posting the code into next comment Please check it. It's working for me – Abhishek Sharma Jan 13 '17 at 14:23
  • var count = 0 func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { print(text) let trimmedString = text.trimmingCharacters(in: .whitespaces) if(trimmedString.characters.count != 0){ count += 1 print(count) } return true } – Abhishek Sharma Jan 13 '17 at 14:23

2 Answers2

3

Please use this code. It will work fine and hope It will be perfectly working with your existing logic.

 var count = 0
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        print(text)
        let trimmedString = text.trimmingCharacters(in: .whitespaces)
        if(trimmedString.characters.count != 0){
        count += 1
        print(count)
        }
        return true
    }

Answer for both question 1 and 2 is When you select text from the predictive text. First, it appends word then It appends a space. That's the reason delegate is called twice.

Abhishek Sharma
  • 475
  • 3
  • 13
  • 1
    and if textView's `text` or `attributedText` property is modified inside this delegate method then it is called thrice – Shyam Feb 15 '18 at 10:08
  • I'm experiencing the same issue that @Shyam described. Somewhat hacky but effective solution described by Richard Venable at https://stackoverflow.com/a/26789344 – Nathan Dudley Feb 14 '20 at 07:20
0

The text view calls this method whenever the user types a new character or deletes an existing character. Implementation of this method is optional. You can use this method to replace text before it is committed to the text view storage. For example, a spell checker might use this method to replace a misspelled word with the correct spelling.

from apple docs https://developer.apple.com/reference/uikit/uitextviewdelegate/1618630-textview

Sulthan
  • 128,090
  • 22
  • 218
  • 270
Alex McPherson
  • 3,185
  • 3
  • 30
  • 41