Search code examples
iosswiftuitextfieldcombine

Swift Combine - How to get a Publisher that delivers events for every character change of UITextField's text property


I noticed that

textField.publisher(for: \.text)

delivers events when editing finishes, but not for every character/editing change. How do I get a Publisher, that sends evens for every change? In ReactiveSwift it would be

textField.reactive.continousTextValues()

And in RxSwift it would be just (How do you get a signal every time a UITextField text property changes in RxSwift)

textField.rx.text

Approaches I took:

  • checking the publisher(for:options:) method, but there are no appropriate options for the desired outcome.
  • adding a target/action textField.addTarget(self, action: #selector(theTextFieldDidChange), for: .editingChanged) (UITextField text change event)
  • doing essentially the same as the previous step by connecting the action via interface builder, both leading to extra work and cluttered code.
  • Watching the 2019 WWDC videos about Combine. They were not dealing with textfields, but using @Published variables instead, hiding were the values actually came from - (or did I miss something?).

I have no clue at the moment, how to do this and I feel the tendency to go back to ReactiveSwift, but I wanted to ask you, before taking this step backwards.


Solution

  • Unfortunately, Apple didn't add publishers for this to UIKit and because UIControl doesn't implement KVO the publisher(for:) publisher doesn't work quite as expected. If you're okay with adding a dependency to your project there are a couple of good UIControl publishers here.

    Alternatively, you could implement your own publisher that does this, or subscribe to textfield changes the old school way.