RxSwift / RxCocoa: запретить UITextField иметь больше символов

Я хотел бы, чтобы UITextField был настроен с помощью RxSwift / RxCocoa, чтобы он содержал только до ... символов. Я не хочу использовать для этого UITextFieldDelegate, но хотел бы добиться этого с помощью RxSwift / RxCocoa. Есть ли способ сделать это?


person swalkner    schedule 14.02.2018    source источник


Ответы (1)


Конечно:

textField.rx.controlEvent(.editingChanged).subscribe(onNext: { [unowned self] in
    if let text = self.textField.text {
        self.textField.text = String(text.prefix(40))
    }
}).disposed(by: disposeBag)

В этом примере текстовое поле ограничено 40 символами.

Редактировать:

Сохранение предыдущего значения при достижении лимита.

textField.rx.text.orEmpty
.scan("") { (previous, new) -> String in
    if new.count > 40 {
        return previous ?? String(new.prefix(40))
    } else {
        return new
    }
}
.subscribe(textField.rx.text)
.disposed(by: disposeBag)

Вероятно, это можно адаптировать для соблюдения других правил ...

Обратите внимание, однако, что при достижении лимита символов ваш курсор переместится в конец текстового поля.

person Valérian    schedule 14.02.2018
comment
Это близко, но не совсем то, что я ищу. Например. если текстовое поле имеет 40 символов, и пользователь вводит символ в начале, я хотел бы предотвратить это и оставить содержимое без изменений, в вашем случае будет взят новый символ, а последний исчезнет. - person swalkner; 15.02.2018
comment
Отредактировал мой пост, чтобы ответить на ваши дополнительные критерии. Надеюсь это поможет. - person Valérian; 15.02.2018
comment
@ Валериан за отредактированный ответ, String(new.prefix(40)) в return previous ?? String(new.prefix(40)) никогда не будет выполняться, значение previous никогда не будет равно нулю, так зачем вы его добавляете? - person mojtaba al moussawi; 04.09.2018
comment
К сожалению, компилятор делает предыдущий необязательным, потому что textField.rx.text ожидает необязательную строку. Вы можете избавиться от этого, добавив .map { Optional($0) } между scan и subscribe. - person Valérian; 04.09.2018
comment
@ Валериан previous не является обязательным и никогда не станет обязательным! Я имел в виду, что для String(new.prefix(40)) нет смысла и он никогда не будет выполнен, поскольку предыдущий не является необязательным. Вы сделали его необязательным, заполнив Scan пустой строкой _4 _... - person mojtaba al moussawi; 04.09.2018
comment
Хотя я теоретически согласен с вами, используя приведенный выше код в моем проекте, компилятор считает его необязательным, хотя этого не следует делать. Вы пробовали на своей стороне? - person Valérian; 04.09.2018
comment
Да @ Валериан, я считаю это необязательным. - person mojtaba al moussawi; 04.09.2018
comment
Как получить символ набора UITextfield в Rxswift? Может кто-нибудь мне помочь? - person McDonal_11; 11.11.2019
comment
@ Valérian Например, текстовое поле изначально пустое, а затем ограничение составляет 2 символа. Если программно я установил значение следующим образом: textfield.text = 123. Текстовое поле все равно будет пустым. Как вместо этого получить 12? - person iori24; 04.01.2020
comment
Установка текста, как вы упомянули, не вызывает управляющего события, поэтому у вас, вероятно, происходит что-то еще. Вы можете добавить операторы отладки в последовательность, чтобы подтвердить это. - person Valérian; 06.01.2020
comment
Правда. .scan("") { previous, new in (new.count > 40) ? previous : new } достаточно. - person SoftDesigner; 30.12.2020