Замена RxSwift должна изменитьCharactersInRange - PullRequest
0 голосов
/ 28 мая 2018

Я хочу использовать UITextfield с RxSwift.Моя цель - разрешить / не вводить символ на клавиатуре пользователя и удалить символ из вставки копии, мне нужно обработать делегат UITextfield "shouldChangeCharactersInRange" с RxSwift .

Как реализовать с RxSwift ?

Я использую RxSwift версии 4. Случай 1: Ввод с клавиатуры: A123 Процесс из RxSwift: Принять 123 (не допускается NumberPad)Выходные данные: 123

Случай 2: Форма ввода Копировать Вставить из контактов: \ U202d1111111111 \ U202c Процесс из RxSwift: удалить все управляющие символы, принять 1111111111 Выход: 1111111111

Если в общем случае мы можем использовать shouldChangeCharactersInRange, но как использовать с RxSwift?

Ответы [ 2 ]

0 голосов
/ 13 августа 2018

Как правило, вы не должны изменять статус в shouldChangeCharactersInRange, даже если вы не используете Rx.Этот обратный вызов - это запрос, а не команда.Текстовое поле просто спрашивает вас, должно ли оно выполнять поведение по умолчанию, а не запрашивает его обновление.Поведение, которое вы пытаетесь реализовать, должно быть в действии 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)
        }
    }
}

Кстати, даже если вы представляете клавиатуру с цифровой клавиатурой, вам все равно понадобится такой код, потому что пользователь может подключить клавиатуру Bluetooth и, следовательно, может вводить не числа.

0 голосов
/ 08 августа 2018

Вы можете наблюдать за обновлением текста и возвращать его при необходимости:

Observable.zip(textfield.rx.text, textfield.rx.text.skip(1))
    .subscribe(onNext: { (old, new) in
        if $invalid {
            textfield.text = old
        }
    })
...