SwiftUI - Как установить максимальное число в TextField? - PullRequest
0 голосов
/ 27 мая 2020

Для моего приложения мне нужно, чтобы пользователь ввел число от 1 до 1000, и я хотел бы убедиться, что оно находится между этими числами. Сначала я подумал об использовании Stepper, но затем пользователю пришлось бы нажимать + тысячу раз. Есть лучший способ сделать это? Я сделал так, чтобы пользователю предлагалось ввести numberPad, но это позволяет пользователю вводить любое число.

Вот мой код:

@State var validityPeriod = ""

var body: some View {
    NavigationView {
        Form {
            TextField("Validity Period (In Days)", text: $validityPeriod)
        }
        .navigationBarTitle("Validation")
    }
}

Я могу проверить номер, который они вводится перед отправкой формы, но я бы предпочел что-то, что проверяет поле во время ввода.

Примечание: я использую Xcode 11.5 с Swift 5

1 Ответ

2 голосов
/ 27 мая 2020

Вы можете проверить правильность текущего значения с помощью вычисленного свойства Bool. Затем в любом месте вы можете поместить эту проверку в свой код.

SwiftUI воссоздает ContentView body каждый раз, когда ваша переменная @State изменяется (что лучше всего сделать закрытым, к вашему сведению). У него есть некоторый интеллект в повторном рендеринге только того, что необходимо, но по существу переоценивается весь ваш View, и ваш вычисленный bool periodIsValid повторно тестируется при каждом нажатии клавиши.

Довольно часто кнопка отправки отключена, пока форма недействительна . Что-то вроде:

Button(...) {
    ...
}
.disabled(!periodIsValid)

Чтобы сделать это вживую, вы можете сделать ряд творческих вещей с этой живой проверкой. Что-то действительно простое - заставить введенный текст стать красным, если он недействителен:

struct ContentView: View {
    @State private var validityPeriod = ""

    var periodIsValid: Bool {
        guard let days = Int(validityPeriod) else { return false}
        guard days >= 1 && days <= 1000 else { return false }
        return true
    }

    var body: some View {
        NavigationView {
            Form {
                TextField("Validity Period (In Days)", text: $validityPeriod)
                    .foregroundColor(periodIsValid ? .primary : .red)
            }
            .navigationBarTitle("Validation")
        }
    }
}

Изменить:

Вы также можете ограничить значения ввода ...

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

Для этого вы используете свойство didSet обертка. Единственная загвоздка в том, что он не работает с оболочкой @State, поэтому вам придется использовать вместо него @ObservedObject. Довольно просто ...

Одно замечание: вы можете помочь людям понять, что происходит. Если ваш интерфейс еще не дает понять, какие значения допустимы, вы можете указать подсказку, когда вы вводите sh недопустимую запись.

class ValidityPeriod: ObservableObject {
    @Published var validityPeriod = "" {
        didSet {
            // Allow blanks in the field, or they can't delete
            if validityPeriod == "" { return }

            // Check the entire value is good, otherwise ignore the change
            let days = Int(validityPeriod) ?? 0
            if days < 1 || days > 1000 { validityPeriod = oldValue }

            // Pop alert or trigger any other UI instruction here
        }
    }
}

struct ContentView: View {

    @ObservedObject var vp = ValidityPeriod()

    var body: some View {
        NavigationView {
            Form {
                TextField("Validity Period (In Days)", text: $vp.validityPeriod)
            }
            .navigationBarTitle("Validation")
        }
    }
}
...