多个UITextField和textDidChangeNotification通知

时间:2019-06-23 20:21:37

标签: swift uikit combine

我最近正在使用Combine框架,想知道是否有可能创建一些智能扩展以使发布者更改文本。

假设我有两个UITextField:

firstTextField.textPub.sink {
    self.viewModel.first = $0
}

secondTextField.textPub.sink {
    self.viewModel.second = $0
}

其中第一个和第二个变量只是`@Published var first / second:String =“”

extension UITextField {
    var textPub: AnyPublisher<String, Never> {
        return NotificationCenter.default
            .publisher(for: UITextField.textDidChangeNotification)
            .map {
                guard let textField = $0.object as? UITextField else { return "" }
                return textField.text ?? ""
            }
            .eraseToAnyPublisher()
    }
}

这不起作用,因为我使用的是NotificationCenter共享实例,因此,当我对任何textField进行任何更改时,它都会将新值传播到两个sink闭包中。您是否认为有任何方法可以实现类似于RxSwift中可用的rx.text的功能?我当时正在考虑将addTarget与闭包一起使用,但这需要使用Objective-C中的关联对象。

2 个答案:

答案 0 :(得分:1)

我知道了。我们可以使用NotificationCenter传递对象,然后过滤所有与我们的实例不匹配的实例。它似乎按我预期的那样工作:

extension UITextField {
    var textPublisher: AnyPublisher<String, Never> {
        NotificationCenter.default
            .publisher(for: UITextField.textDidChangeNotification, object: self)
            .compactMap { $0.object as? UITextField }
            .filter { $0 == self }
            .map { $0.text ?? "" }
            .eraseToAnyPublisher()
    }
}

答案 1 :(得分:0)

我建议您将订阅者添加到视图模式,并在视图控制器的上下文中将其连接为文本字段发布者。

NotificationCenter可用于在整个应用范围内调度事件;连接View Controller完全拥有的项目时,无需使用它。但是,一旦更新了视图模式,就可以将一个“ View Modal Did Change”事件发布到NotificationCenter。