3

The TextView delegate is set:

textView.delegate = self //self being a UITextViewDelegate

but the delegate method doesn't get called when the text is set programmatically

func textViewDidChange(_ textView: UITextView) {
    print(textView.text)
}

How to respond to text changes without going reactive?

ielyamani
  • 17,807
  • 10
  • 55
  • 90
  • You probably need to add something to whatever function is changing the text... Or, possibly subclass `UITextView` and add your own "watching for changes" code. – DonMag Apr 07 '17 at 12:17

4 Answers4

3

This is how UITextField (and most of UIKit controls) behave- doesn't trigger event when set programatically. It makes sense- lets you avoid recurring, infinite calls.

If you really want to be notify when text is changed programatically, you have to subclass UITextField and override text property (probably attributedText also). Then in didSet block call delegate method.

Don't forget that UITextField inherits from UIControl- I would also call sendActions(for:) to make target-action mechanism fire.

psci
  • 903
  • 9
  • 18
  • The OP is asking about `UITextView`, not `UITextField`. Most of your answer is relevant but unfortunately, `UITextView` does not inherit from `UIControl` so it's not possible to call `sendActions(for:)`. – Jay Whitsitt Jan 05 '18 at 16:57
2

I just tried KVO on UITextView,

 self.textView1.text = "You are working, but I will change you in 5 seconds"

Add your observer

self.textView1.addObserver(self, forKeyPath: "text", options: NSKeyValueObservingOptions(rawValue: 0), context: nil)

Trigger text change programmatically, just an example do it the way you want.

 DispatchQueue.main.asyncAfter(deadline:.now() + 5) {
    self.textView1.text = "Changed after some time"
}

Override the KVO method.

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

FYI from Apple docs below

Note: Although the classes of the UIKit framework generally do not support KVO, you can still implement it in the custom objects of your application, including custom views.

https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/KVO.html

Satheesh
  • 10,998
  • 6
  • 50
  • 93
0
  1. declare your text view variable with @objc dynamic
  2. declare and hold a variable with type NSKeyValueObservation
  3. use function observe(_:changeHandler:) bind your text view's text property, hold the return value with variable declared in step 2
  4. observe changes in changeHandler

example:

@objc dynamic private var textView: UITextView!
private var observation: NSKeyValueObservation?

func bind() {
    observation = observe(\.textView.text, options: [.old, .new]) { object, change in
        print(object, change)
    }
}
LiLi Kazine
  • 195
  • 2
  • 9
-2

You have misspelled the delegate with textView with _textView

func textViewDidChange(textView: UITextView) { //Handle the text changes here
        print(textView.text); //the textView parameter is the textView where text was changed
    }

Put this in viewDidLoad

textView!.delegate = self
Saranjith
  • 11,242
  • 5
  • 69
  • 122