8

If I am typing with the keyboard, then textViewDidChange and shouldChangeTextInRange are always called. But when I change the textView programmatically, the delegate methods aren't called. How do I get a programmatic change in textView to trigger delegate methods?

Update

Is there some other way for simulating keyboard input programmatically?

Katedral Pillon
  • 14,534
  • 25
  • 99
  • 199
  • what exactly changed to programmatically, mean ?? ... are you sure about the delegate ? – Kumar KL Sep 26 '14 at 09:47
  • write down the code where you are changing the text rather the calling delegates – Jay Gajjar Sep 26 '14 at 09:48
  • @KumarKL it means setting the `text` attribute via code. – Nicola Miotto Sep 26 '14 at 09:48
  • Check the textfield as set for the delegate and in .h file added the textFieldDelegate ? – Kumar KL Sep 26 '14 at 09:50
  • 3
    The question is too simple for all these requests for clarification. It makes the people asking look like they don't know how to code or how to read. The OP is doing `textView.text=@"some text";` as opposed to typing it with the keyboard. Also, @KumarKL if the delegate were not set, how would it be possible that they are called for keyboard input. Come on: just read the question. Simple. – Konsol Labapen Sep 26 '14 at 09:55
  • **But when I change the textView programmatically,?** How you are doing this .? show us some stuff. – Kumar KL Sep 26 '14 at 10:05
  • 1
    I don't have to know the answer to find all these request ridiculous. I don't mean to hurt your ego. But the question is so clear I had to say something to stop the madness. I don't mean to pick on you, as you weren't the only one asking. But it was getting to the point where someone might come and ask what does `delegate` mean. Again: the question is clear! – Konsol Labapen Sep 26 '14 at 10:07
  • @KumarKL I am doing `textView.text=@"some text"` in the code. But apparently not all changes to the UITextView trigger the delegates. – Katedral Pillon Sep 26 '14 at 10:09

2 Answers2

10

I solve this issue in my code using the insert method instead to change the value of the text string.

textView.insertText("Your Text")
Maximo Lucosi
  • 378
  • 4
  • 9
1

Just ran into this question a few years later but had a hard time finding other good answers, so I want to demonstrate Satheesh's technique answered here with greater detail that worked for me for future readers and people that experience a similar issue.

Technique

First, add an observer to the textView:

let property = "text" //can also be attributedText for attributed strings
self.textView.addObserver(self, forKeyPath: property, options: NSKeyValueObservingOptions(rawValue: 0), context: nil)

Next, override the observeValue function:

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        
    if object as? NSObject == self.textView { 
        //your code here
    }
    
}

The observeValue function will run after the property value of the textView you added the observer to has been changed. Note that when you programmatically set the text of the textView like:

textView.text = "programmatically assigned text"

The shouldChangeTextIn delegate function is ran before the observer is called. As a side note, if you are using attributedText as the property, I would also recommend setting the property in that function and returning false:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        
        let newString = NSString(string: textView.text!).replacingCharacters(in: range, with: text)
        textView.attributedText = createAttributedString(text: newString)
        return false
    
}

This ensures that you do not duplicate the text you are inputting into the text and attributedText properties. You can also use the delegate function to reject input, such as new lines, and it will not call the observeValue function. To re-iterate, that function is only called after the shouldChangeTextIn function returns true or false.

If there are any mistakes here or anything else someone else would like to add, feel free to let me know.

Happy programming!

BITWISE
  • 115
  • 1
  • 8