简体   繁体   中英

UITextView data change swift

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
    }
}

Set delegate of UITextView .Refer UITextViewDelegate

Write this in viewDidLoad

bodyText!.delegate = self

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)?

}

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 .

When subclassing UITextView:

import UIKit
class SelfAwareTextView: UITextView {
    
    func setup() {
        NotificationCenter.default.addObserver(self,
         selector: #selector(change),
         name: UITextView.textDidChangeNotification,
         object: self)
    }
    
    @objc func change(_ notif: Notification) {
        print("the user edited the text. It's now: " + text)
    }
}

In add observor, the object: is the sending object.

Somewhat confusingly, you set that to self since, in fact, we simply want notifications from ourself; we don't care about other text views.

Regarding setup , recall that (in general) when subclassing a UITextView, you want to do setup in awakeFromNib rather than init, etc, since, among other issues you then catch any IBInspectable values.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM