Как создать регулярное выражение даты с Swift? - PullRequest
1 голос
/ 20 апреля 2019

Я пытаюсь создать строку регулярного выражения для даты, например this .Мой код (пример Swift 5):

let dateValidator = TextValidator(input: dateTextField.rx.text.asObservable(), regex: try! NSRegularExpression(pattern:
    #"^\s*(3[01]|[12][0-9]|0?[1-9])\.(1[012]|0?[1-9])\.((?:19|20)\d{2})\s*$"#))

let v = Observable.combineLatest(dateValidator.validate(), anotherValidator.validate()) {
    (date, another) in
    return date && another
}
//another code

class TextValidator {
    var input: Observable<String?>
    var regex: NSRegularExpression

    init(input: Observable<String?>, regex: NSRegularExpression) {
        self.input = input
        self.regex = regex
    }

    func validate() -> Observable<Bool> {
        return input.map { text in
            let range = NSRange(location: 0, length: text!.utf8.count)
            return self.regex.firstMatch(in: text!, options: [], range: range) != nil
        }
    }
}

И я получаю ошибку:

Завершение работы приложения из-за необработанного исключения «NSRangeException», причина: «*** - [NSRegularExpressionenumerateMatchesInString: options: range: usingBlock:]: диапазон или индекс вне границ '

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

1 Ответ

1 голос
/ 20 апреля 2019

Получая NSRange из Swift String, вы хотите использовать utf16 вместо utf8:

func validate() -> Observable<Bool> {
    return input.map { text in
        guard let text = text else { return false }
        let range = NSRange(location: 0, length: text.utf16.count)
        return self.regex.firstMatch(in: text, range: range) != nil
    }
}

Лично я нахожу логику между выбором utf8 илиutf16 неоправданно непрозрачен, и я использую инициализатор NSRange(_:in:):

func validate() -> Observable<Bool> {
    return input.map { text in
        guard let text = text else { return false }
        let range = NSRange(text.startRange..., in: text)
        return self.regex.firstMatch(in: text, range: range) != nil
    }
}

При этом использование utf8.count при сборке NSRange только проявит этот сбой, если строкав нем были символы не ASCII.Возможно, это объясняет, почему, когда вы исправили это с помощью utf16, сбой исчез, но ваша проверка по-прежнему не проходит.Строки должны содержать расширенные символы Юникода и, следовательно, по определению не соответствуют регулярному выражению.

...