1

I have been trying to limit the number of characters I can input on a TextField in SwiftUI while at the same time only allow digits.

I have tried a mixed solution based on this and this

.onReceive(Just(viewModel.myString)) { newValue in
    let filtered = newValue.filter { "0123456789".contains($0) }
    if filtered != newValue {
        self.viewModel.myString = filtered
    }
}

to filter the characters and also

@Published var myString: String = "" {
    willSet {
        if newValue.count > Constants.maxLimit {
            myString = String(newValue.prefix(Constants.maxLimit))
        }
    }
}

to limit the amount of characters.

But with this approach, I can still add more than Constants.maxLimit and add characters other than numbers.

And if I try to combine both logic to either willSet/didSet in the view model or onReceive on the textfield, I get a crash caused by an overflow of the stack.

I'm still pretty new at SwiftUI so, I'm not really sure if a custom Publisher will help solve my case.

Asif Mujtaba
  • 447
  • 6
  • 17
  • Can't you do just? : `.onReceive(Just(viewModel.myString)) { newValue in let filtered = newValue.filter { "0123456789".contains($0) } if filtered != newValue, filtered.count <= Constants.maxLimit { self.viewModel.myString = filtered } }` – Fahri Azimov Aug 10 '20 at 04:30

1 Answers1

0

You can simply filter all characters that is whole number and get the first 10 characters of the resulting string. You would need also to check if the string is empty and set the value back to zero:


import SwiftUI
import Combine

struct ContentView: View {
    @State private var text = "0"
    let maxLength = 10
    var body: some View {
        TextField("", text: $text)
            .keyboardType(.numberPad)
            .onReceive(Just(text)) {
                guard !$0.isEmpty else {
                    self.text = "0"
                    return
                }
                if let value = Int($0.filter(\.isWholeNumber).prefix(maxLength)) {
                    self.text = String(value)
                }
        }
    }
}
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571