问题描述
我想将UITextfield与RxSwift一起使用.我的目标是允许/禁止在用户键盘中输入字符并从复制粘贴中删除字符,我需要使用 RxSwift 处理UITextfield的委托"shouldChangeCharactersInRange".
I want use UITextfield with RxSwift. My goal is allowing/not input character in User keyboard and removing character from copy paste, I need handle UITextfield's delegate "shouldChangeCharactersInRange" with RxSwift.
如何使用 RxSwift 实施?
我正在使用RxSwift版本4.情况1:键盘输入:A123从RxSwift处理:接受123(不允许使用NumberPad)输出:123
I am using RxSwift version 4.Case 1: Input from keyboard: A123Process from RxSwift : Accept 123 (not allowing NumberPad)Output : 123
情况2:输入表格从联系人复制粘贴:\ U202d1111111111 \ U202c从RxSwift处理:删除所有控制字符,接受1111111111输出:1111111111
Case 2:Input form Copy Paste from Contacts: \U202d1111111111\U202cProcess from RxSwift : remove all control character, accept 1111111111Output: 1111111111
如果通常我们可以使用shouldChangeCharactersInRange,但是如何与RxSwift一起使用?
If in general we can use shouldChangeCharactersInRange , but how to use with RxSwift?
推荐答案
通常,即使您不使用Rx,也不应在shouldChangeCharactersInRange
中对状态进行突变.该回调是查询而不是命令.该文本字段仅询问您是否应执行默认行为,而不是告诉您对其进行更新.您尝试实现的行为应该在editChanged操作中.
In general, you should not be mutating state in shouldChangeCharactersInRange
, even if you aren't using Rx. That callback is a query not a command. The textfield is merely asking you if it should perform the default behavior, not telling you to update it. The behavior you are trying to implement should be in the editingChanged action.
由于您使用的是Rx,因此文本字段的rx.text
观察者等效于editedChanged操作,应改为使用.该过程中最困难的部分是,如果用户要在字符串的中间插入/删除,请确保不会丢失用户的位置.
Since you are using Rx, the text field's rx.text
observer is equivalent to the editingChanged action and should be used instead. The hardest part of the procedure is making sure you don't loose the user's place if they are inserting/deleting in the middle of the string.
在您的viewDidLoad中:
In your 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)
}
}
}
顺便说一句,即使您正在展示数字键盘,您仍然需要这样的代码,因为用户可能已经连接了蓝牙键盘,因此仍然可以输入非数字.
BTW, even if you are presenting the number pad keyboard, you still need some code like this because the user might have a bluetooth keyboard hooked up and thus could still enter non-numbers.
这篇关于RxSwift替换应该ChangeCharactersInRange的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!