我想在Uxextfield中使用RxSwift。我的目标是在用户键盘中允许/不输入字符并从复制粘贴中删除字符,我需要处理UITextfield的委托" shouldChangeCharactersInRange"使用 RxSwift 。
如何使用 RxSwift 实现?
我正在使用RxSwift版本4。 情况1: 键盘输入:A123 来自RxSwift的过程:接受123(不允许使用NumberPad) 输出:123
案例2: 输入表单从联系人复制粘贴:\ U202d1111111111 \ U202c 从RxSwift处理:删除所有控制字符,接受1111111111 输出:1111111111
如果一般我们可以使用shouldChangeCharactersInRange,但如何使用RxSwift?
答案 0 :(得分:4)
通常,即使您不使用Rx,也不应在shouldChangeCharactersInRange
中对状态进行突变。该回调是查询而不是命令。该文本字段只是询问您是否应执行默认行为,而不是告诉您对其进行更新。您尝试实现的行为应该在editChanged操作中。
由于您使用的是Rx,因此文本字段的rx.text
观察者等效于editChanged操作,应改为使用。该过程中最困难的部分是,如果用户要在字符串的中间插入/删除,请确保不要失去用户的位置。
在您的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)
}
}
}
顺便说一句,即使您正在展示数字键盘,您仍然需要这样的代码,因为用户可能已经连接了蓝牙键盘,因此仍然可以输入非数字。
答案 1 :(得分:-1)
您可以观察文本更新并在必要时将其还原:
Observable.zip(textfield.rx.text, textfield.rx.text.skip(1))
.subscribe(onNext: { (old, new) in
if $invalid {
textfield.text = old
}
})