Swift Combine - 如何让 Publisher 为 UITextField 文本的每个字符更改传送事件 属性
Swift Combine - How to get a Publisher that delivers events for every character change of UITextField's text property
我注意到
textField.publisher(for: \.text)
在编辑完成时提供事件,但不是针对每个 character/editing 更改。我如何获得发布者,它会为每次更改发送消息?
在 ReactiveSwift 中它将是
textField.reactive.continousTextValues()
而在 RxSwift 中它只是 (How do you get a signal every time a UITextField text property changes in RxSwift)
textField.rx.text
我采用的方法:
- 正在检查
publisher(for:options:)
方法,但没有适合所需结果的选项。
- 添加一个 target/action
textField.addTarget(self, action: #selector(theTextFieldDidChange), for: .editingChanged)
(UITextField text change event)
- 通过界面生成器连接动作,与上一步基本相同,这都会导致额外的工作和混乱的代码。
- 正在观看有关 Combine 的 2019 WWDC 视频。他们没有处理文本字段,而是使用
@Published
变量,隐藏值实际上来自 - (或者我错过了什么?)。
目前我不知道如何做到这一点,我觉得有回到 ReactiveSwift 的趋势,但我想问你,在倒退这一步之前。
您始终可以根据需要创建自定义发布者。例如,我在这里创建了 TextField 发布者,它包装了 textField 的 textFieldDidChange 操作,并在每个字符 entered/deleted 之后发送 String!请复制 link,所以不解析它:
https://github.com/DmitryLupich/Combine-UIKit/blob/master/CombineCustomPublishers/%20 出版商/TextFieldPubisher.swift
不幸的是,Apple 没有为此向 UIKit 添加发布者,并且因为 UIControl 没有实现 KVO,所以 publisher(for:)
发布者没有按预期工作。如果您愿意为您的项目添加依赖项,那么有几个不错的 UIControl 发布者 here.
或者,您可以实现自己的发布者来执行此操作,或者以旧的方式订阅文本字段更改。
如果这是您要查找的内容,我猜 UITextField
会发出通知和控制事件,因此您可以通过收听通知来实现,例如:
import UIKit
import Combine
class ViewController: UIViewController {
@IBOutlet private var textField: UITextField!
var cancellables = Set<AnyCancellable>()
override func viewDidLoad() {
super.viewDidLoad()
let textFieldPublisher = NotificationCenter.default
.publisher(for: UITextField.textDidChangeNotification, object: textField)
.map( {
([=10=].object as? UITextField)?.text
})
textFieldPublisher
.receive(on: RunLoop.main)
.sink(receiveValue: { [weak self] value in
print("UITextField.text changed to: \(value)")
})
.store(in: &cancellables)
}
}
让我知道这是否是您的实际目标。
如果是 UITextField,您可以使用此扩展:
extension UITextField {
func textPublisher() -> AnyPublisher<String, Never> {
NotificationCenter.default
.publisher(for: UITextField.textDidChangeNotification, object: self)
.map { ([=10=].object as? UITextField)?.text ?? "" }
.eraseToAnyPublisher()
}
}
用作:textField.textPublisher()
我注意到
textField.publisher(for: \.text)
在编辑完成时提供事件,但不是针对每个 character/editing 更改。我如何获得发布者,它会为每次更改发送消息? 在 ReactiveSwift 中它将是
textField.reactive.continousTextValues()
而在 RxSwift 中它只是 (How do you get a signal every time a UITextField text property changes in RxSwift)
textField.rx.text
我采用的方法:
- 正在检查
publisher(for:options:)
方法,但没有适合所需结果的选项。 - 添加一个 target/action
textField.addTarget(self, action: #selector(theTextFieldDidChange), for: .editingChanged)
(UITextField text change event) - 通过界面生成器连接动作,与上一步基本相同,这都会导致额外的工作和混乱的代码。
- 正在观看有关 Combine 的 2019 WWDC 视频。他们没有处理文本字段,而是使用
@Published
变量,隐藏值实际上来自 - (或者我错过了什么?)。
目前我不知道如何做到这一点,我觉得有回到 ReactiveSwift 的趋势,但我想问你,在倒退这一步之前。
您始终可以根据需要创建自定义发布者。例如,我在这里创建了 TextField 发布者,它包装了 textField 的 textFieldDidChange 操作,并在每个字符 entered/deleted 之后发送 String!请复制 link,所以不解析它:
https://github.com/DmitryLupich/Combine-UIKit/blob/master/CombineCustomPublishers/%20 出版商/TextFieldPubisher.swift
不幸的是,Apple 没有为此向 UIKit 添加发布者,并且因为 UIControl 没有实现 KVO,所以 publisher(for:)
发布者没有按预期工作。如果您愿意为您的项目添加依赖项,那么有几个不错的 UIControl 发布者 here.
或者,您可以实现自己的发布者来执行此操作,或者以旧的方式订阅文本字段更改。
如果这是您要查找的内容,我猜 UITextField
会发出通知和控制事件,因此您可以通过收听通知来实现,例如:
import UIKit
import Combine
class ViewController: UIViewController {
@IBOutlet private var textField: UITextField!
var cancellables = Set<AnyCancellable>()
override func viewDidLoad() {
super.viewDidLoad()
let textFieldPublisher = NotificationCenter.default
.publisher(for: UITextField.textDidChangeNotification, object: textField)
.map( {
([=10=].object as? UITextField)?.text
})
textFieldPublisher
.receive(on: RunLoop.main)
.sink(receiveValue: { [weak self] value in
print("UITextField.text changed to: \(value)")
})
.store(in: &cancellables)
}
}
让我知道这是否是您的实际目标。
如果是 UITextField,您可以使用此扩展:
extension UITextField {
func textPublisher() -> AnyPublisher<String, Never> {
NotificationCenter.default
.publisher(for: UITextField.textDidChangeNotification, object: self)
.map { ([=10=].object as? UITextField)?.text ?? "" }
.eraseToAnyPublisher()
}
}
用作:textField.textPublisher()