At latest version (5.0.3). Related to this change:
Continuous text signals of UITextField now emits the latest value for all editing events emitted. In other words, replacements due to autocompletions are now covered by the signals. (#3442 , kudos to @andersio)
Code snippet:
import UIKit
import ReactiveSwift
import ReactiveCocoa
internal class ViewController: UIViewController {
@IBOutlet internal var textField: UITextField!
internal var textProperty: MutableProperty<String> = MutableProperty("")
internal override func viewDidLoad() -> Void {
super.viewDidLoad()
let textSignal = self
.textField
.reactive
.continuousTextValues
.skipNil()
.filter({ (value: String) -> Bool in
return (value.characters.count == 4)
})
.map { (value: String) -> String in
self.textField.resignFirstResponder() //*** -[NSLock lock]: deadlock (<NSLock: 0x6000000d2b40> 'org.reactivecocoa.ReactiveSwift.Signal.sendLock')
return value
}
self.textProperty <~ textSignal
}
}
This is a legitimate use case. That's said we are limited by both the UIControl API and non-recursive requirement of Signal here, and we need a sensible umbrella default which covers the potential change of value with editingDidEnd and editingDidEndOnExit.
If autocompletion is not a concern, you may consider controlEvents(for: .editingChanged). Otherwise, it seems asynchronously scheduling resignFirstResponder would be the only option.
@andersio thanks for hint, controlEvents(for: .editingChanged) has resolved my issue.
Most helpful comment
This is a legitimate use case. That's said we are limited by both the UIControl API and non-recursive requirement of
Signalhere, and we need a sensible umbrella default which covers the potential change of value witheditingDidEndandeditingDidEndOnExit.If autocompletion is not a concern, you may consider
controlEvents(for: .editingChanged). Otherwise, it seems asynchronously schedulingresignFirstResponderwould be the only option.