我想将 UITextfield 与 RxSwift 一起使用。我的目标是允许/不允许在用户键盘中输入字符并从复制粘贴中删除字符,我需要使用 RxSwift 处理 UITextfield 的委托(delegate)“shouldChangeCharactersInRange”。
如何用RxSwift实现?
我正在使用 RxSwift 版本 4。 情况1: 键盘输入:A123 来自 RxSwift 的进程:接受 123(不允许 NumberPad) 输出:123
案例二: 从联系人输入表单复制粘贴:\U202d1111111111\U202c 来自 RxSwift 的过程:删除所有控制字符,接受 1111111111 输出:1111111111
如果一般情况下我们可以使用 shouldChangeCharactersInRange ,但是如何与 RxSwift 一起使用呢?
最佳答案
一般来说,你不应该在 shouldChangeCharactersInRange
中改变状态,即使你没有使用 Rx。该回调是查询而不是命令。文本字段只是询问您是否应该执行默认行为,而不是告诉您更新它。您尝试实现的行为应该在 editingChanged 操作中。
由于您使用的是 Rx,因此文本字段的 rx.text
观察器等同于 editingChanged 操作,应该改为使用。该过程中最困难的部分是确保您不会丢失用户在字符串中间插入/删除的位置。
在你的viewDidLoad中:
textField.rx.text.orEmpty
.map(digitsOnly)
.subscribe(onNext: setPreservingCursor(on: textField))
.disposed(by: bag)
支持全局函数:
func digitsOnly(_ text: String) -> String {
return text.components(separatedBy: CharacterSet.decimalDigits.inverted).joined(separator: "")
}
func setPreservingCursor(on textField: UITextField) -> (_ newText: String) -> Void {
return { newText in
let cursorPosition = textField.offset(from: textField.beginningOfDocument, to: textField.selectedTextRange!.start) + newText.count - (textField.text?.count ?? 0)
textField.text = newText
if let newPosition = textField.position(from: textField.beginningOfDocument, offset: cursorPosition) {
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
}
}
}
顺便说一句,即使您提供的是数字键盘,您仍然需要这样的代码,因为用户可能连接了蓝牙键盘,因此仍然可以输入非数字。
关于ios - RxSwift 替换 shouldChangeCharactersInRange,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50558613/