Reputation: 11153
I'm trying to create a custom phone formatter. I found PhoneNumberKit that could work for my particular case, the problem with this is that when I tried it there are multiple issues like:
.international
the program enters in a loop and becomes irresponsiveSo, what I'm trying to do is to create my own PhoneFormatter, something like: (###) ###-####
, currently this might suffice as we're only targeting a single country and this is the most common format used here.
I'm following the code from this site to get an idea of how to do it, but here they are working with dates:
struct ContentView: View {
static let taskDateFormat: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .long
return formatter
}()
var dueDate = Date()
var body: some View {
Text("Task due date: \(dueDate, formatter: Self.taskDateFormat)")
}
}
Someone asked something similar 2 years ago on Apple's Developer Forums but I believe it was for UIKit rather than SwiftUI and there's no code shown there.
I'm trying to attach my formatter directly to my own TextField
, I've tried looking for something similar with SwiftUI and I haven't found anything, and still can't find myself how to create my own custom formatter using something like formatter.numberStyle = "(###) ###-####"
Could anyone point me in the right direction?
Upvotes: 1
Views: 544
Reputation: 11
Try editing the dictionary to your desire...
let testCountries: [ PhoneNumberFormat ] = [
PhoneNumberFormat ( id: "United States" ,flagEmoji: "🇺🇸" , leadingDigits: "+1" , format: "+X (XXX) XXX-XXXX" ),
PhoneNumberFormat ( id: "Argentina" ,flagEmoji: "🇦🇷" , leadingDigits: "+54" , format: "+XX (X) XXXX-XXXX" ),
PhoneNumberFormat ( id: "Austria" ,flagEmoji: "🇦🇹" , leadingDigits: "+43" , format: "+XX (X) XXXXX-XXXX" ),
PhoneNumberFormat ( id: "Brazil" ,flagEmoji: "🇧🇷" , leadingDigits: "+55" , format: "+XX (XX) XXXX-XXXX" ),
PhoneNumberFormat ( id: "Canada" ,flagEmoji: "🇨🇦" , leadingDigits: "+1" , format: "+X (XXX) XXX-XXXX" ),
PhoneNumberFormat ( id: "China" ,flagEmoji: "🇨🇳" , leadingDigits: "+86" , format: "+XX (XXX) XXXX-XXXX" ),
PhoneNumberFormat ( id: "France" ,flagEmoji: "🇫🇷" , leadingDigits: "+33" , format: "+XX (X) XX XX XX XX" ),
PhoneNumberFormat ( id: "Germany" ,flagEmoji: "🇩🇪" , leadingDigits: "+49" , format: "+XX (XXX) XXXXXXX" ),
PhoneNumberFormat ( id: "India" ,flagEmoji: "🇮🇳" , leadingDigits: "+91" , format: "+XX XXXXX-XXXXX" ),
PhoneNumberFormat ( id: "Italy" ,flagEmoji: "🇮🇹" , leadingDigits: "+39" , format: "+XX (XXX) XXXXXXX" ),
]
@main
struct PhoneNumberApp: App {
@State var PN: String = ""
var body: some Scene {
WindowGroup {
PhoneNumberField()
}
}
}
struct PhoneNumberFormat: Identifiable {
let id: String
let flagEmoji: String
let leadingDigits: String
let format: String
}
struct PhoneNumberField: View {
@State private var country: String = "United States"
@State var phoneNumber: String = ""
private var data: PhoneNumberFormat { testCountries.first ( where: { $0.id == self.country } )! }
var body: some View {
HStack {
Picker("Hide Label", selection: $country, content: {
ForEach ( testCountries , id: \.id ) { PN_Data in
Text ( PN_Data.id )
}
}) .frame ( maxWidth: 200 ) .labelsHidden()
Text ( self.data.flagEmoji )
TextField ( "" , text: self.$phoneNumber.phoneNumberFormat ( self.data ) )
.onAppear { self.phoneNumber = data.leadingDigits }
.onChange ( of: self.country ) { nv in self.phoneNumber = data.leadingDigits }
}
}
}
extension Binding where Value == String {
func phoneNumberFormat ( _ data: PhoneNumberFormat ) -> Binding<String> {
return Binding (
get: {
self.wrappedValue
},
set: { newValue in
DispatchQueue.main.async {
let filteredString = newValue.filter { $0.isNumber }
var formattedString = ""
var currentNumberIndex = filteredString.startIndex
var patternIndex = data.format.startIndex
while patternIndex < data.format.endIndex && currentNumberIndex < filteredString.endIndex {
if data.format [ patternIndex ] == "X" {
formattedString.append ( filteredString[currentNumberIndex ] )
currentNumberIndex = filteredString.index(after: currentNumberIndex)
} else {
formattedString.append ( data.format [ patternIndex ] )
}
patternIndex = data.format.index ( after: patternIndex )
}
self.wrappedValue = formattedString
guard newValue.hasPrefix ( data.leadingDigits ) else { self.wrappedValue = data.leadingDigits ; return }
}
}
)
}
}
Upvotes: 0