I am attempting to format the data in a SwiftUI TextField with a pattern or mask. (For clarity - NOT a UITextField). One example would be a US phone number. So the user can type 1115551212 and the result in the view is 111-555-1212. I'll use a numberPad in this case, but for future, with the full keyboard, if the user types a non-number, I'd like to be able to replace it with something, say 0. So entering 111abc1212 would result in 111-000-1212. Even though the code below converts the string to numbers, ideally, I want the mask to operate on a String not a number - giving the flexibility to format part numbers etc.
I have been able to do this with a func that operates from a button, but of course I want it to be automatic. I have been completely unsuccessful with SwiftUI modifiers to do the same. And using the built in .textContentType(.telephoneNumber) does absolutely nothing in my tests.
I would expect to have some modifier like .onExitCommand that can execute when the focus leaves the TextField but I don't see a solution.
This code works with the button (I will later add rules to filter for numbers when numbers are expected):
struct ContentView: View {
@State private var phoneNumber = ""
@State private var digitArray = [1]
var body: some View {
VStack {
Group {//group one
Text("Phone Number with Format").font(.title)
.padding(.top, 40)
TextField("enter phone number", text: $phoneNumber)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
.keyboardType(.numberPad)
}//Group one
Group {//group two
Button(action: {self.populateTextFieldWithPhoneFormat(phoneString: self.phoneNumber)}) {
Text("Convert to Phone Format")
}
}//group two
Spacer()
}//VStack
}
func populateTextFieldWithPhoneFormat(phoneString: String) {
var digitArray = [Int]()
let padded = phoneNumber.padding(toLength: 10, withPad: "0", startingAt: 0)
let paddedArray = padded.map {String($0)}
for char in paddedArray {
digitArray.append(Int(char) ?? 0)
}
phoneNumber = format(digits: digitArray)
}//populate
func format(digits: [Int]) -> String {
var phone = digits.map(String.init)
.joined()
if digits.count > 3 {
phone.insert("-", at: phone.index(
phone.startIndex,
offsetBy: 3)
)
}
if digits.count > 7 {
phone.insert("-", at: phone.index(
phone.startIndex,
offsetBy: 7)
)
}
return phone
}
}
I also attempted to make my own ViewModifier, but got nowhere.
Xcode Version 11.2.1 (11B500)