RxSwift替换应该ChangeCharactersInRange

Dav*_*adi 6 ios swift rx-swift

我想将UITextfield与RxSwift一起使用。我的目标是让用户键盘/不输入字符和复制粘贴删除角色,我需要处理的UITextField的委托“shouldChangeCharactersInRange”与RxSwift

如何用RxSwift实现?

我正在使用版本4的RxSwift。情况1:来自键盘的输入:A123来自RxSwift的进程:接受123(不允许数字键盘)输出:123

情况2:从联系人处输入表单复制粘贴:\ U202d1111111111 \ U202c从RxSwift处理:删除所有控制字符,接受1111111111输出:1111111111

如果总的来说,我们可以使用shouldChangeCharactersInRange,但是如何与RxSwift一起使用呢?

Dan*_* T. 8

通常,shouldChangeCharactersInRange即使您不使用Rx,也不应在中更改状态。该回调是查询而不是命令。该文本字段只是询问您是否应执行默认行为,而不是告诉您对其进行更新。您尝试实现的行为应该在editChanged操作中。

由于使用的是Rx,因此文本字段的rx.text观察者等效于editedChanged操作,应改为使用。该过程中最困难的部分是确保用户在字符串中间插入/删除时不要失去其位置。

在您的viewDidLoad中:

textField.rx.text.orEmpty
    .map(digitsOnly)
    .subscribe(onNext: setPreservingCursor(on: textField))
    .disposed(by: bag)
Run Code Online (Sandbox Code Playgroud)

支持全局功能:

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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,即使您正在展示数字键盘,您仍然需要这样的代码,因为用户可能已经连接了蓝牙键盘,因此仍然可以输入非数字。