chausovSurfStudio / TextFieldsCatalog

This is catalog of various input field with great opportunities for validation and formatting.
MIT License
25 stars 8 forks source link

Конфликт maskFormatter и maxLength #94

Open NullIsOne opened 4 years ago

NullIsOne commented 4 years ago

Если задать maskFormatter одновременно с maxLength то ограничения из маски будут приоритетнее.

Пример:

/// маска ограничивает на 21 символ
field.maskFormatter = MaskTextFieldFormatter(mask: "[_][~~~~~~~~~~~~~~~~~~~~]", notations: [ Notation(character: "~", characterSet: characterSet, isOptional: true)])

field.maxLength = 20

При вводе в поле позволяется ввести 21 символ.

Быть может так и задумано, но это неочевидно.

chausovSurfStudio commented 3 years ago

интересный поинт) самому эта шляпа не нравится, давай попробуем вместе разобраться, что с ней не так

есть такой вот кусок кода, который как раз срабатывает в условиях из описания

open func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        guard
            let text = textField.text,
            let textRange = Range(range, in: text),
            !validateWithFormatter,
            let maxLength = self.maxLength
        else {
            return true
        }

        let newText = text.replacingCharacters(in: textRange, with: string)
        return newText.count <= maxLength
    }

соответственно, если validateWithFormatter стоит по умолчанию в false - то будет проверка не в соответствии с маской, а по полю maxLength. Правильно понимаю, что в твоем кейсе validateWithFormatter видимо установлен в true? И потому maxLength игнорируется

И второй есть момент, где validateWithFormatter участвует - это метод validate, который валидирует либо по логике в маске (а там фактически валидация проходит, если из недр InputMask либы приходит флаг о том, что inputIsCompleted, иначе - валидация не проходит), либо в соответствие с установленным валидатором.

Как тебе вот лично кажется, есть смысл разделить это поле на два в соответствие с двумя этими кейсами? Или же просто более полно задокументировать?

NullIsOne commented 3 years ago

Нет, validateWithFormatter не менялся, то есть стоит значение по-умолчанию - false.

Думаю проблема в том, что тот делегат не вызывается, если была установлена маска

смотри

public var maskFormatter: MaskTextFieldFormatter? {
        didSet {
            if maskFormatter != nil {
                textField.delegate = maskFormatter?.delegateForTextField()
                maskFormatter?.setListenerToFormatter(listener: self)
                textField.autocorrectionType = .no
            } else {
                textField.delegate = self
            }
        }
    }

Стоит наверное ещё уточнить, что у нас на проекте подтянута версия

  - TextFieldsCatalog (0.12.2):
    - InputMask (= 4.0.2)

Но если для 0.12.3 это тоже актуально, то я бы предложил следующее. И маска и лимит символов это ограничение. Как видим в данном случае, они могут быть взаимоисключающими, поэтому может стоит объединить эти опции в одну сущность, через enum или протокол? Например

enum TextFieldLimit {
    case exact(count: Int)
    case mask(formatter: MaskTextFieldFormatter)
}
chausovSurfStudio commented 3 years ago

хм.. норм так импакт) давай подумаю как-нибудь на досуге, погляжу. Ибо смутные воспоминания есть, что при установке маски методы делегата там все-равно должны проксироваться

chausovSurfStudio commented 3 years ago

по этому вопросу - да, я все же понял) есть косяк, безусловно возьму в работу 👌