1

In SwiftUI, I got a textfield where the user is able to enter a credit card no.:

@EnvironmentObject var userModData:UserModData    

var body: some View {

...

HStack {
    Text("Card number")
        .frame(width: 100, height: nil, alignment: .leading)
    TextField("Enter card number", text: $userModData.cnumber).keyboardType(.numberPad)
}

Every time the user types in four digits I'd like to add a space, e. g. it should look like: 1234 5678 1234 5678

In the observable object class, I tried to write

class UserModData:ObservableObject {

    @Published var cnumber:String = " " {
        didSet{
            self.cnumber = self.NumberFormatter()
        }
    }

    func NumberFormatter() -> String {
        var newValue = self.cnumber

        if newValue.count == 4 {
            newValue = newValue + " "
        }

        return newValue
    }
}

This leads to the runtime error EXC_BAD_ACCESS because when the string is concatenated in the function, the didSet code is called over and over again (at least I guess that's the reason because it leads to an overflow?!).

Does anyone got an elegant solution to solve this problem? To be honest, I am pretty new to SwiftUI and I guess the solution is easier than I expected.

Thanks in advance!

Christian
  • 29
  • 4

1 Answers1

4

What you are trying to achive can not be done by SwiftUI because it is not possible to jump at the end of the Textfield with your cursor after you added a Space. (SwiftUI is still just at the beginning.) For this part please take a look at this question.

A correct code for what you are looking for starts with the below code and the answer from the above link has to be implemented:

class UserModData:ObservableObject {
    @Published var cnumber: String = ""
}

struct ContentView : View {

    @ObservedObject var userModData = UserModData()

    var body: some View {
        let cnumber = Binding<String> (
            get: {
                (self.userModData.cnumber )},
            set: { newValue in
                if newValue.count % 4 == 0 {
                    self.userModData.cnumber = newValue + " "
                } else {
                    self.userModData.cnumber = newValue
                }

        })

        return HStack {
            Text("Card number")
                .frame(width: 100, height: nil, alignment: .leading)
            TextField("Enter card number", text: cnumber).keyboardType(.numberPad)
        }
    }
}
Kuhlemann
  • 3,066
  • 3
  • 14
  • 41