Как преобразовать строку к виду телефонного номера?

Изучаю SwiftUI. Необходимо сделать так, чтобы в TextField при вводе номера накладывалась маска("+X (XXX) XXX-XXXX"). Сама функция есть, и она работает. Не могу разобраться, как и где мне ее вызвать, чтобы при изменении строки, пользователь сразу видел изменённую строку.

static func format(with mask: String, phone: String) -> String {
        let numbers = phone.replacingOccurrences(of: "[^0-9]", with: "", options: .regularExpression)
        var result = ""
        var index = numbers.startIndex

        for ch in mask where index < numbers.endIndex {
            if ch == "X" {

                result.append(numbers[index])
                index = numbers.index(after: index)

            } else {
                result.append(ch)
            }
        }
        return result
    }

Ответы (2 шт):

Автор решения: Alex Sonar

На вопрос как?:
Занести возвращаемое функцией значение в объектную переменную, к примеру в yourphoneobject. Кстати функция format принимает еще один строковый аргумент mask поэтому на вход его то же подаем!

На вопрос где?:
Там где нужно вернуть обработанный нашей функцией телефонный номер через объект обращаемся к ней:

var phonenumber: String = "<источник>"
var phonenmask String = "<источник>"

var yourphoneobject = <имя класса где, находится функция format>()
yourphoneobject.format(phonenmask, phonenumber)

далее yourphoneobject применяем или подставляем где требуется вернуть обработанный номер.

Подробнее почитать можно Объектно-ориентированное программирование и Объекты и классы

→ Ссылка
Автор решения: schmidt9

Вот минимальный пример с использованием вашего кода, здесь используется также код отсюда для перемещения курсора при вводе в конец текста, иначе он остается всегда в начале текста и получается, что каждая новая цифра вводится первой. Правда при таком подходе все равно остается проблема перескока курсора в конец текста при исправлении цифры в середине.

import SwiftUI

struct ContentView: View {

    let mask = "+X (XXX) XXX-XXXX"

    @State var text = ""

    var body: some View {

        let textChangedBinding = Binding<String>(get: {
            Self.format(with: self.mask, phone: self.text)
        }, set: {
            self.text = $0
        })

        return TextFieldContainer(mask, text: textChangedBinding)
    }

    static func format(with mask: String, phone: String) -> String {
        let numbers = phone.replacingOccurrences(of: "[^0-9]", with: "", options: .regularExpression)
        var result = ""
        var index = numbers.startIndex

        for ch in mask where index < numbers.endIndex {
            if ch == "X" {
                result.append(numbers[index])
                index = numbers.index(after: index)
            } else {
                result.append(ch)
            }
        }
        return result
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

/************************************************/

///
/// https://stackoverflow.com/a/58841655/3004003
///
struct TextFieldContainer: UIViewRepresentable {
    private var placeholder : String
    private var text : Binding<String>

    init(_ placeholder:String, text:Binding<String>) {
        self.placeholder = placeholder
        self.text = text
    }

    func makeCoordinator() -> TextFieldContainer.Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: UIViewRepresentableContext<TextFieldContainer>) -> UITextField {

        let innertTextField = UITextField(frame: .zero)
        innertTextField.placeholder = placeholder
        innertTextField.text = text.wrappedValue
        innertTextField.delegate = context.coordinator
        innertTextField.keyboardType = .numberPad // << added by schmidt9

        context.coordinator.setup(innertTextField)

        return innertTextField
    }

    func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<TextFieldContainer>) {
        uiView.text = self.text.wrappedValue
    }

    class Coordinator: NSObject, UITextFieldDelegate {
        var parent: TextFieldContainer

        init(_ textFieldContainer: TextFieldContainer) {
            self.parent = textFieldContainer
        }

        func setup(_ textField:UITextField) {
            textField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
        }

        @objc func textFieldDidChange(_ textField: UITextField) {
            self.parent.text.wrappedValue = textField.text ?? ""

            let newPosition = textField.endOfDocument
            textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
        }
    }
}
→ Ссылка