Как отформатировать строку ввода TextField по функции? - PullRequest
1 голос
/ 28 октября 2019

У меня есть простое TextField для ввода по телефону, и я хочу форматировать его каждый раз, когда оно меняется.

Я использую PhoneNumberKit, и он работает нормально, но я не понимаю, как вызвать функцию форматирования после изменения значения в textField.

Функция форматирования телефона.

import SwiftUI
import PhoneNumberKit
import Combine

func formatTelephone(telephone : String) -> String
    {

        do {
            let phoneNumber =  PartialFormatter().formatPartial(telephone)

            print(phoneNumber)
            return phoneNumber
        }
        catch {
            print("Generic parser error")

        }
    }

Он делает что-то вроде этого:

formatTelephone("79152140700") -> "7 (915) 214 08-00" 
formatTelephone("791521") -> "7 (915) 21" 

, и у меня есть такой TextField

TextField("915 214 07 00" , text: $telephoneManager.telephone)

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

1 Ответ

0 голосов
/ 28 октября 2019

Чтобы получить то, что вы хотите, вам нужно использовать Combine (реализация двух методов в модели представления зависит от вас, поскольку они строго зависят от ваших потребностей):

import SwiftUI
import Combine

class ContentViewModel: ObservableObject {
    @Published var phoneNumber = ""
    private var toCancel: AnyCancellable!

    init() {
        toCancel = $phoneNumber
            .filter { !self.isFormatValid($0) }
            .map { self.convert($0) }
            .receive(on: RunLoop.main)
            .assign(to: \.phoneNumber, on: self)
    }

    private func isFormatValid(_ str: String) -> Bool {
        //here you must check if _str_ is already in the right format
        true //just to make this example compile, but clearly this must be replaced with your code
    }

    private func convert(_ str: String) -> String {
        //convert your string to be in the right format
        "string in the correct format" //just to make this example compile, but clearly this must be replaced with your code
    }

    deinit {
        toCancel.cancel()
    }
}

struct ContentView: View {
    @ObservedObject var contentViewModel = ContentViewModel()

    var body: some View {
        TextField("Your phone number...", text: $contentViewModel.phoneNumber)
    }
}

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

Шаги(посмотрите на представление модели init):

  1. phoneNumber - это свойство @Published, поэтому «оно поддерживается» издателем, на которого вы можете подписаться. Итак, давайте подпишемся на этого издателя.
  2. Вы должны проверить, находится ли строка в вашем текстовом поле в правильном формате. Это имеет первостепенное значение: если вы пропустите этот шаг, вы получите бесконечный цикл. Это делается с помощью оператора .filter. Событие пересылается вниз, только если оператор .filter возвращает true (в этом случае он возвращает true, если формат строки недопустим).
  3. С помощью оператора .map вы можете изменить строку (в неправильномформат) и вернуть строку в нужном формате.
  4. .receive позволяет переслать событие в интересующий вас поток. В этом случае основной поток (так как вы хотите обновить текстовое поле).
  5. .assign просто присваивает новое значение текстовому полю.
...