UITextField text change event

后端 未结 21 1326
南方客
南方客 2020-11-22 06:49

How can I detect any text changes in a textField? The delegate method shouldChangeCharactersInRange works for something, but it did not fulfill my need exactly.

21条回答
  •  天涯浪人
    2020-11-22 07:31

    1. KVO solutions do not work

    KVO does NOT work in iOS for controls: http://stackoverflow.com/a/6352525/1402846 https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/KVO.html

    1. In the observing class, you do this:

    Given that you know the text view you want to watch:

    var watchedTextView: UITextView!
    

    Do this:

    NotificationCenter.default.addObserver(
        self,
        selector: #selector(changed),
        name: UITextView.textDidChangeNotification,
        object: watchedTextView)
    

    However, be careful with that:

    • it's likely you only want to call that once, so do not call it in, for example, layoutSubviews

    • it's quite difficult to know when to best call it during your bring-up process. It will depend on your situation. Unfortunately there is no standard, locked-in solution

    • for example you usually certainly can not call it at init time, since of course watchedTextView may not exist yet

    .

    1. the next problem is that ...

    None of the notifications are called when text is changed programmatically.

    This is a huge, age-old, and stupid, nuisance in iOS engineering.

    Controls simply do not - end of story - call the notifcations when the .text property is changed programmatically.

    This is insanely annoying because of course - obviously - every app ever made sets the text programmatically, such as clearing the field after the user posts, etc.

    You have to subclass the text view (or similar control) like this:

    class NonIdioticTextView: UIITextView {
    
        override var text: String! {
            // boilerplate code needed to make watchers work properly:
            get {
                return super.text
            }
            set {
                super.text = newValue
                NotificationCenter.default.post(
                    name: UITextView.textDidChangeNotification,
                    object: self)
            }
    
        }
    
    }
    

    (Tip - don't forget the super call has to come before ! the post call.)

    There is no solution available, unless, you fix the control by subclassing as shown just above. That is the only solution.

    Note that the notification

    UITextView.textDidChangeNotification
    

    results in

    func textViewDidChangeSelection(_ textView: UITextView) 
    

    being called.

    (Not textViewDidChange .)

提交回复
热议问题