How do you get a signal every time a UITextField text property changes in ReactiveCocoa 5

How do you get a signal from user-initiated and programmatically made changes to the UITextField text property? When using continuousTextValues only the signal is output when the user initiated the change. If you programmatically set textField.text , the signal does not fire.

This is how I use continuousTextValues :

 textField.reactive.continuousTextValues.observeValues { value in print("Value: \(value)") } 

It does not start if I install text manually:

 textField.text = "Test" 
+9
source share
5 answers

The continuousTextValues signal will be triggered only during user input from the keyboard. You can try the following:

 var characters = MutableProperty("") tf.reactive.text <~ characters tf.reactive.continuousTextValues.observeValues { [weak characters = characters] (text) in characters?.value = text! } tf.reactive.textValues.observeValues { [weak characters = characters] (text) in characters?.value = text! } characters.producer.skip(while: { $0.isEmpty }).startWithValues { (text) in log.debug("text = \(text)") } characters.value = "shaw" 
+5
source

Instead of changing the text value with textField.text you need to create a signal, bind it to the text field and change the signal value. I used the Signal channel, but if you need to save a programmatically changed value, you can use MutableProperty .

 class MyViewController: UIViewController { var textField: UITextField! private let textFieldValuePipe = Signal<String?, NoError>.pipe() var textFieldValueSignal: Signal<String?, NoError>! override func viewDidLoad() { // Initialize the text field // ... // Bind the text of the text field to the signal pipe output textField.reactive.text <~ textFieldValuePipe.output // A signal of text values emitted by the text field upon end of editing. let textFieldValuesSignal = textField.reactive.textValues // A signal of text values emitted by the text field upon any changes. let textFieldContinuousValuesSignal = textField.reactive.continuousTextValues // Merge the relevant signals textFieldValueSignal = Signal.merge(textFieldValuesSignal, textFieldContinuousValuesSignal, textFieldValuePipe.output) // This will print the text field value when it changed by the user or programmatically textFieldValueSignal.observeValues { value in print(value ?? "nil") } } // Use this to change the text field value programmatically func setTextFieldText(_ text: String?) { textFieldValuePipe.input.send(value: text) } } 
+1
source

To listen for programmatic changes to a text property:

 let textField = UITextField() let signal = textField.reactive.signal(forKeyPath: #keyPath(UITextField.text)).map { $0 as? String } signal.observeValues { print($0) } textField.text = "Hello World" 

Please note that you still need to observe continuousTextValues if you want to observe changes due to user actions.

0
source

You can listen to textFields using the rac_textSignal property.

 [self.someTextField.rac_textSignal subscribeNext:^(NSString* text) { NSLog(@"%@", text); }]; 

Each time textField texts change, this closure will be called.

0
source

If it is possible to subclass UITextField , you can override text and force it to trigger an editing event after customization with: textField.sendActions(for: .editingChanged)

0
source

Source: https://habr.com/ru/post/1262367/


All Articles