Auto Format Phone numbers, Zipcode Using @PropertyWrapper SwiftUI
Find Code — https://github.com/gsachin/SwiftUISamples/tree/main/AutoFormatter

import Foundation

import SwiftUI

// Define number of enum to support auto formating

enum AutoFormatterType {

case phone

case zipcode

}

// Extension to format and deformat Test

// accepting list symbol(char/string) and it index position in which symbol need to inserted

extension String {

func formatString(symbols:[Int:String])->String {

var formattedComponents = [String]()

self.forEach {

if let symbol = symbols[formattedComponents.count] {

// inserting symbols at its index position to format a text

formattedComponents.append(symbol)

}

if “0123456789”.contains($0){

formattedComponents.append(“\($0)”)

}

}

return formattedComponents.joined()

}

func deformatString()->String {

return self.filter {

//removing symbols

return “0123456789”.contains($0)

}

}

}

//creation generic Auto Formatter proporty wrapper

@propertyWrapper struct AutoFormatter : DynamicProperty {

var type:AutoFormatterType

//A Dictionary to hold the list of symbol and its index position

private var symbolsToInsert = [Int:String]()

@State private var value = “”

// Here we are doing the magic populating symbol and its index position to symbolsToInsert

init(type:AutoFormatterType) {

self.type = type

switch type {

case .phone:

symbolsToInsert[0] = “(“

symbolsToInsert[4] = “) “

symbolsToInsert[8] = “-”

case .zipcode:

symbolsToInsert[5] = “-”

}

}

var wrappedValue: String {

get {

value

}

nonmutating set {

value = newValue

}

}

var projectedValue:Binding<String> {

Binding(get:{

wrappedValue.formatString(symbols: symbolsToInsert)

},

set: {

wrappedValue = $0.deformatString()

}

)

}

}

//Now in View we can use AutoFormatter property wrapper

struct ContentView: View {

//property wrapper for phone number

@AutoFormatter(type:.phone) var phoneNumber:String

//property wrapper for Zip Code

@AutoFormatter(type:.zipcode) var zipCode:String

var body: some View {

VStack {

Text(“Text Formatting”)

.padding()

TextField(“Phone Number”, text: $phoneNumber).onReceive(phoneNumber.publisher.collect()) {

//phoneNumber char limit validation

self.phoneNumber = String($0.prefix(10))

}

TextField(“ZipCode”, text: $zipCode) .onReceive(zipCode.publisher.collect()) {

//zipCode char limit validation

self.zipCode = String($0.prefix(9))

}

Spacer()

}.padding(20)

}

}

struct ContentView_Previews: PreviewProvider {

static var previews: some View {

ContentView()

}

}
['Sachin Gupta']
['Swiftui', 'Property Wrapper', 'Formatter', 'Text', 'Swiftui Text Formatter']