Reactivecocoa: Deadlock caused by resignFirstResponder

Created on 13 Apr 2017  路  2Comments  路  Source: ReactiveCocoa/ReactiveCocoa

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
    }
}
bug

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 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.

All 2 comments

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

RuiAAPeres picture RuiAAPeres  路  3Comments

iby picture iby  路  5Comments

tunidev picture tunidev  路  3Comments

mdiep picture mdiep  路  5Comments

gabro picture gabro  路  5Comments