#ios #swift #swiftui
#iOS #swift #swiftui
Вопрос:
Я рассмотрел разные ответы на этот вопрос, но я в замешательстве. Я относительно новичок в Swift. В настоящее время я работаю над своим выпускным проектом для школы. Хотелось бы, чтобы кто-нибудь ответил на вопрос, но также углубился в детали. Текущее поведение соответствует только 0-9. Я не могу заставить его выполнять число 10.
struct ContentView: View {
// Private vars for tracking
@State private var hoursSlept = 0;
// *** What happens if the user enters something other than an integer/double?
@State private var depressedMood = ""
@State private var elevatedMood = ""
@State private var anxietyMood = ""
@State private var irritabilityMood = ""
@State private var maxLength = 1;
// Var for button
@State private var enterButtonPress = false
var body: some View {
VStack {
NavigationView {
Form {
// Hours slept last night (0-24)
Stepper(value: $hoursSlept, in: 0...24, label: {
Text("Hours slept last night: (self.hoursSlept)")
})
TextField("Depression 0-10", text: $depressedMood)
.keyboardType(.numberPad)
.onReceive(Just(depressedMood)) {
guard !$0.isEmpty else {
self.depressedMood = ""
return
}
if let value = Int($0.filter(.isWholeNumber).prefix(maxLength)) {
self.depressedMood = String(value)
}
}
TextField("Elevation 0-10", text: $elevatedMood)
.keyboardType(.numberPad)
.onReceive(Just(elevatedMood)) {
guard !$0.isEmpty else {
self.elevatedMood = ""
return
}
if let value = Int($0.filter(.isWholeNumber).prefix(maxLength)) {
self.elevatedMood = String(value)
}
}
TextField("Anxiety 0-10", text: $anxietyMood)
.keyboardType(.numberPad)
.onReceive(Just(anxietyMood)) {
guard !$0.isEmpty else {
self.anxietyMood = ""
return
}
if let value = Int($0.filter(.isWholeNumber).prefix(maxLength)) {
self.anxietyMood = String(value)
}
}
TextField("Irritability 0-10", text: $irritabilityMood)
.keyboardType(.numberPad)
.onReceive(Just(irritabilityMood)) {
guard !$0.isEmpty else {
self.irritabilityMood = ""
return
}
if let value = Int($0.filter(.isWholeNumber).prefix(maxLength)) {
self.irritabilityMood = String(value)
}
}
Комментарии:
1. Вы пытались создать
Formatter
и передать его в текстовое поле?2.
maxLength
установлено значение1
. Чего бы вы ожидали?3. Когда я устанавливаю maxLength = 2, это делает числа больше 11.
4. Я не знаю, как создать форматировщик. Просматриваю его сейчас. Какие-нибудь ресурсы, которые вы знаете наверху, для моей ситуации?
5. Что вам нужно, так это сохранить последнее значение и установить максимальное значение. Проверьте, превышает ли текущее значение максимально допустимое, если true, верните его к последнему значению, в противном случае оставьте как есть.
Ответ №1:
Вот возможное решение — используйте ~=
и проверьте, находится ли значение в диапазоне:
struct ContentView: View {
@State private var depressedMood = ""
var body: some View {
TextField("Depression 0-10", text: $depressedMood)
.keyboardType(.numberPad)
.onReceive(Just(depressedMood)) {
guard let value = Int($0), 0...10 ~= value else {
self.depressedMood = ""
return
}
self.depressedMood = String(value)
}
}
}
Комментарии:
1. Я бы сохранил последнее значение вместо очистки поля
2. Правда, я только что сохранил решение OP, которое использует
self.depressedMood = ""
.3. Не имеет смысла изменять содержимое текстового поля, когда вводится что-то недопустимое
Ответ №2:
Вам следует попробовать пользовательское текстовое поле, чтобы вы могли управлять логикой. Затем вы можете привязать его к любому текстовому полю, которое вы хотите.
class TextBindingManager: ObservableObject {
@Published var text = "" {
didSet {
guard let newValue = Int(text) else {
text = oldValue
return
}
if( !(newValue >= range.lowerBound) || !(newValue <= range.upperBound)) {
text = oldValue
}
}
}
let range: Range<Int>
init(limit: Range<Int> = 0..<10){
range = limit
}
}
Затем вы можете использовать его так, как вам нравится, привязав его
struct MyView: View {
@ObservedObject var textBindingManager = TextBindingManager()
var body: some View {
TextField("", text: $textBindingManager.text, onEditingChanged: { _ in }, onCommit: {})
}
}
Комментарии:
1.
guard let newValue = Int(text), range ~= newValue else {
Ответ №3:
вы могли бы использовать что-то простое вроде этого:
struct ContentView: View {
@State var depressedMood = ""
var body: some View {
VStack {
TextField("0-10", text: $depressedMood)
.keyboardType(.numberPad)
.onChange(of: depressedMood) {
let txt = $0.filter("0123456789".contains)
if let num = Int(txt), num <= 10, txt.count <= 2 {
depressedMood = txt
} else {
depressedMood = String(txt.dropLast())
}
}
}
}
}
Комментарии:
1.
$0.filter("0123456789".contains)
2. да, более лаконично, это тоже будет хорошо работать. Я обновлю свой ответ этим вместе с добавленным ограничением текста.