Reputation: 8365
How do you get a signal from both user-initiated and programmatically made changes to UITextField
text
property? By using continuousTextValues
only reports a signal when the user has initiated the change. If you set textField.text
programmatically, the signal doesn't fire.
This is how I'm using continuousTextValues
:
textField.reactive.continuousTextValues.observeValues { value in
print("Value: \(value)")
}
It doesn't get triggered if I set text
manually:
textField.text = "Test"
Upvotes: 10
Views: 4299
Reputation: 32273
After setting the text, trigger the editing event: textField.sendActions(for: .editingChanged)
Upvotes: 0
Reputation: 169
To listen to programmatic changes in 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"
Note that you still need to observe continuousTextValues
if you want to observe changes due to user actions.
Upvotes: 0
Reputation: 1401
Instead of changing the text value with textField.text
, you have to create a signal, bind it to the text field and modify the signal's value. I've used a Signal
pipe but if you need to store the programmatically changed value, you can use a 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's 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's value when it's changed by the user or programmatically
textFieldValueSignal.observeValues { value in
print(value ?? "nil")
}
}
// Use this to change the text field's value programmatically
func setTextFieldText(_ text: String?) {
textFieldValuePipe.input.send(value: text)
}
}
Upvotes: 1
Reputation: 92
The signal continuousTextValues
will only be triggered while user input using the keyboard.You could try this:
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"
Upvotes: 5