How can you detect a change of data in a UITextView
with Swift
? The following code does not do any detection.
I am declaring the UITextView
:
@IBOutlet weak var bodyText: UITextView!
optional func textViewDidChange(_ textView: UITextView!) {
println(bodyText.text)
}
Thanks Scott
You need to set UITextView delegate and implement textViewDidChange: method in it. Unfortunately, I do not know if swift documentation is available online. All the links go to the objective-c documentation.
The code will look like this: (updated for SWIFT 4.2)
class ViewController: UIViewController, UITextViewDelegate { //If your class is not conforms to the UITextViewDelegate protocol you will not be able to set it as delegate to UITextView
@IBOutlet weak var bodyText: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
bodyText.delegate = self //Without setting the delegate you won't be able to track UITextView events
}
func textViewDidChange(_ textView: UITextView) { //Handle the text changes here
print(textView.text); //the textView parameter is the textView where text was changed
}
}
For my case, I wanted the implementation to be independent from a UIViewController, so i dont need to assign a delegate just for text changes. Or even maybe there is some kind of validation on the UITextView, and you wanna contain it per field instead of a delegate managing a lot of complicated logic.
It requires to subclass UITextView, but its very much worth it imo:
class TextView: UITextView {
convenience init() {
self.init(frame: CGRect.zero, textContainer: nil)
NotificationCenter.default.addObserver(self, selector: #selector(textDidChangeNotification), name: UITextView.textDidChangeNotification , object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
@objc func textDidChangeNotification(_ notif: Notification) {
guard self == notif.object as? UITextView else {
return
}
textDidChange()
}
func textDidChange() {
// the text in the textview just changed, below goes the code for whatever you need to do given this event
// or you can just set the textDidChangeHandler closure to execute every time the text changes, useful if you want to keep logic out of the class
textDidChangeHandler?()
}
var textDidChangeHandler: (()->Void)?
}
Set delegate
of UITextView
.Refer UITextViewDelegate
Write this in viewDidLoad
bodyText!.delegate = self
For Swift 4:
func textViewDidChange(_ textView: UITextView) {
// Your code here
}
For Swift 4.2, you can add UITextViewTextDidChange
, UITextViewTextDidBeginEditing
& UITextViewTextDidEndEditing
notification observers to a UITextView like this:
let nc = NotificationCenter.default
nc.addObserver(self, selector: #selector(textViewDidChange), name: NSNotification.Name.UITextViewTextDidChange , object: nil)
nc.addObserver(self, selector: #selector(textViewDidBeginEditing), name: NSNotification.Name.UITextViewTextDidBeginEditing , object: nil)
nc.addObserver(self, selector: #selector(textViewDidEndEditing), name: NSNotification.Name.UITextViewTextDidEndEditing , object: nil)
And the observers look like this:
@objc func textViewDidChange(_ notif: Notification) {
guard notif.object is UITextView else { return }
// Do something
}
@objc func textViewDidBeginEditing(_ notif: Notification) {
guard notif.object is UITextView else { return }
// Do something
}
@objc func textViewDidEndEditing(_ notif: Notification) {
guard notif.object is UITextView else { return }
// Do something
}
For Swift5, the format of the 'name' values are UITextView.textDidChangeNotification
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With